createHttpClient function
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
);
};
}