interceptResponse method

  1. @override
FutureOr<BaseResponse> interceptResponse({
  1. required BaseResponse response,
})

Runs after the response is received. Return the (possibly modified) response.

Implementation

@override
FutureOr<BaseResponse> interceptResponse({
  required BaseResponse response,
}) async {
  final request = response.request;
  final nf = request == null ? null : _inFlight[request];
  if (nf == null) return response;

  // The interceptor chain runs before `Response.fromStream`, so
  // `interceptResponse` always receives a `StreamedResponse`. To record
  // the body we have to drain that one-shot stream ourselves and hand
  // back a fresh response carrying the same bytes.
  if (!captureResponseBody || response is! StreamedResponse) {
    try {
      nf.complete(
        status: response.statusCode,
        responseHeaders: Map<String, String>.from(response.headers),
        responseBodySize: response.contentLength,
      );
    } catch (_) {}
    return response;
  }

  // Buffer the stream once so we can both log the body and hand the
  // caller an untouched-looking response. Buffering is what
  // `Response.fromStream` already does internally, so for typical JSON
  // APIs this isn't extra overhead.
  final Uint8List bytes;
  try {
    bytes = await response.stream.toBytes();
  } catch (err) {
    try {
      nf.fail(err);
    } catch (_) {}
    rethrow;
  }

  try {
    final body = utf8.decode(bytes, allowMalformed: true);
    nf.complete(
      status: response.statusCode,
      responseHeaders: Map<String, String>.from(response.headers),
      responseBody: _cap(body),
      responseBodySize: bytes.length,
    );
  } catch (_) {}

  return StreamedResponse(
    Stream<List<int>>.value(bytes),
    response.statusCode,
    contentLength: bytes.length,
    request: response.request,
    headers: response.headers,
    isRedirect: response.isRedirect,
    persistentConnection: response.persistentConnection,
    reasonPhrase: response.reasonPhrase,
  );
}