transformResponse method
transformResponse allows changes to the response data before
it is passed to ResponseInterceptor.
Note: As an agreement, you must return the responseBody
when the Options.responseType is ResponseType.stream.
Implementation
@override
Future<dynamic> transformResponse(
RequestOptions options,
ResponseBody responseBody,
) async {
final responseType = options.responseType;
// Do not handled the body for streams.
if (responseType == ResponseType.stream) {
return responseBody;
}
final int totalLength;
if (options.onReceiveProgress != null) {
totalLength = int.parse(
responseBody.headers[Headers.contentLengthHeader]?.first ?? '-1',
);
} else {
totalLength = 0;
}
final streamCompleter = Completer<void>();
int finalLength = 0;
// Keep references to the data chunks and concatenate them later.
final chunks = <Uint8List>[];
final subscription = responseBody.stream.listen(
(Uint8List chunk) {
finalLength += chunk.length;
chunks.add(chunk);
options.onReceiveProgress?.call(finalLength, totalLength);
},
onError: (Object error, StackTrace stackTrace) {
streamCompleter.completeError(error, stackTrace);
},
onDone: () {
streamCompleter.complete();
},
cancelOnError: true,
);
options.cancelToken?.whenCancel.then((_) {
return subscription.cancel();
});
await streamCompleter.future;
// Copy all chunks into the final bytes.
final responseBytes = Uint8List(finalLength);
int chunkOffset = 0;
for (final chunk in chunks) {
responseBytes.setAll(chunkOffset, chunk);
chunkOffset += chunk.length;
}
// Return the finalized bytes if the response type is bytes.
if (responseType == ResponseType.bytes) {
return responseBytes;
}
final isJsonContent = Transformer.isJsonMimeType(
responseBody.headers[Headers.contentTypeHeader]?.first,
);
final String? response;
if (options.responseDecoder != null) {
final decodeResponse = options.responseDecoder!(
responseBytes,
options,
responseBody..stream = Stream.empty(),
);
if (decodeResponse is Future) {
response = await decodeResponse;
} else {
response = decodeResponse;
}
} else if (!isJsonContent || responseBytes.isNotEmpty) {
response = utf8.decode(responseBytes, allowMalformed: true);
} else {
response = null;
}
if (response != null &&
response.isNotEmpty &&
responseType == ResponseType.json &&
isJsonContent) {
return jsonDecodeCallback(response);
}
return response;
}