send method
Sends an HTTP request and asynchronously returns the response.
Implementers should call BaseRequest.finalize to get the body of the
request as a ByteStream. They shouldn't make any assumptions about the
state of the stream; it could have data written to it asynchronously at a
later point, or it could already be closed when it's returned. Any
internal HTTP errors should be wrapped as ClientExceptions.
Implementation
@override
Future<StreamedResponse> send(BaseRequest request) async {
final timing = HttpClientConnectTiming();
final ttfbSw = Stopwatch()..start();
return runZoned(() async {
final recorder = HttpSpanRecorder.start(
tracerName: InstrumentationScopes.http,
method: request.method,
url: request.url,
supportedPhases: _phases,
);
W3CTraceContextPropagator().inject(
contextWithSpan(Context.current, recorder.span),
request.headers,
_TextMapSetter(),
);
recorder.applyRequestHeaders(request.headers);
try {
final response = await _httpClient.send(request);
recorder.recordPhase(HttpTimingPhase.ttfb, elapsedMs(ttfbSw));
recorder.applyConnectTiming(timing);
recorder.applyResponse(
statusCode: response.statusCode,
reasonPhrase: response.reasonPhrase,
protocolVersion: _protocolVersion(response),
);
recorder.applyResponseHeaders(response.headers);
if (timing.peerAddress == null) {
await recorder.resolvePeerWithDns();
} else {
recorder.applyPeer(address: timing.peerAddress);
}
return _TimedStreamedResponse(response, recorder);
} catch (e, st) {
recorder.applyConnectTiming(timing);
if (timing.peerAddress == null) {
await recorder.resolvePeerWithDns();
}
recorder.onError(e, st);
recorder.end();
rethrow;
}
}, zoneValues: {HttpClientConnectTiming.zoneKey: timing});
}