createHttpClient function

HttpClient createHttpClient(
  1. HttpClient client
)

Creates a HttpClient from io.HttpClient.

io.HttpClient only supports HTTP/1, and hence cannot be used with grpc and full duplex streaming in other protocols.

Implementation

HttpClient createHttpClient(io.HttpClient client) {
  return (creq) async {
    final req = await client.openUrl(creq.method, Uri.parse(creq.url));
    // We don't want compression unless it came from upstream.
    //
    // Ref: https://api.dart.dev/dart-io/HttpClient-class.html
    req.headers.removeAll(io.HttpHeaders.acceptEncodingHeader);
    for (final header in creq.header.entries) {
      req.headers.add(header.name, header.value);
    }
    final sentinel = Sentinel.create();
    creq.signal?.future.then((err) {
      sentinel.reject(err);
      req.abort(err);
    });
    if (creq.body case final body?) {
      await for (final chunk in body) {
        req.add(chunk);
      }
    }
    final res = await sentinel.race(req.close());
    final compressed =
        res.headers.value(io.HttpHeaders.contentEncodingHeader) == 'gzip';
    final headers = Headers();
    res.headers.forEach((key, values) {
      // It automatically decompresses gzip responses, but keeps the
      // original content-length and accept-encoding headers.
      //
      // Ref: https://api.dart.dev/dart-io/HttpClient-class.html
      if (compressed &&
          (key == io.HttpHeaders.contentLengthHeader ||
              key == io.HttpHeaders.contentEncodingHeader)) {
        return;
      }
      for (final value in values) {
        headers.add(key, value);
      }
    });
    return HttpResponse(
      res.statusCode,
      headers,
      res.toBytes(sentinel),
      Headers(), // Trailers are not supported in H/1
    );
  };
}