function h2Request()

in packages/dubbo-node/src/node-universal-client.ts [275:343]


function h2Request(
  sentinel: Sentinel,
  sm: NodeHttp2ClientSessionManager,
  url: string,
  method: string,
  headers: http2.OutgoingHttpHeaders,
  options: Omit<http2.ClientSessionRequestOptions, "signal">,
  onStream: (stream: http2.ClientHttp2Stream) => void
): void {
  const requestUrl = new URL(url, sm.authority);
  if (requestUrl.origin !== sm.authority) {
    const message = `cannot make a request to ${requestUrl.origin}: the http2 session is connected to ${sm.authority}`;
    sentinel.reject(new ConnectError(message, Code.Internal));
    return;
  }
  sm.request(method, requestUrl.pathname + requestUrl.search, headers, {}).then(
    (stream) => {
      stream.session.on("error", sentinel.reject);

      sentinel
        .catch((reason) => {
          if (stream.closed) {
            return;
          }
          // Node.js http2 streams that are aborted via an AbortSignal close with
          // an RST_STREAM with code INTERNAL_ERROR.
          // To comply with the mapping between gRPC and HTTP/2 codes, we need to
          // close with code CANCEL.
          // See https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#errors
          // See https://www.rfc-editor.org/rfc/rfc7540#section-7
          const rstCode =
            reason instanceof ConnectError && reason.code == Code.Canceled
              ? H2Code.CANCEL
              : H2Code.INTERNAL_ERROR;
          return new Promise<void>((resolve) => stream.close(rstCode, resolve));
        })
        .finally(() => {
          stream.session.off("error", sentinel.reject);
        })
        .catch(() => {
          // We intentionally swallow sentinel rejection - errors must
          // propagate through the request or response iterables.
        });

      stream.on("error", function h2StreamError(e: unknown) {
        if (
          stream.writableEnded &&
          unwrapNodeErrorChain(e)
            .map(getNodeErrorProps)
            .some((p) => p.code == "ERR_STREAM_WRITE_AFTER_END")
        ) {
          return;
        }
        sentinel.reject(e);
      });

      stream.on("close", function h2StreamClose() {
        const err = connectErrorFromH2ResetCode(stream.rstCode);
        if (err) {
          sentinel.reject(err);
        }
      });
      onStream(stream);
    },
    (reason) => {
      sentinel.reject(reason);
    }
  );
}