diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 09df23b45..ac9a403ba 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -5,7 +5,10 @@ See the [Migration Guide][] for the complete breaking changes list.** ## Unreleased -*None.* +- Fix `FusedTransformer` (the default transformer) throwing a `FormatException` + on an empty response body when a custom `responseDecoder` is set. It now + returns an empty result, consistent with `SyncTransformer` and + `BackgroundTransformer`. ## 5.10.0 diff --git a/dio/lib/src/transformers/fused_transformer.dart b/dio/lib/src/transformers/fused_transformer.dart index d65df1a21..18d0da639 100644 --- a/dio/lib/src/transformers/fused_transformer.dart +++ b/dio/lib/src/transformers/fused_transformer.dart @@ -92,7 +92,9 @@ class FusedTransformer extends Transformer { decodedResponse = null; } - if (isJsonContent && decodedResponse != null) { + if (isJsonContent && + decodedResponse != null && + decodedResponse.isNotEmpty) { // slow path decoder, since there was a custom decoder specified return jsonDecode(decodedResponse); } else if (customResponseDecoder != null) { diff --git a/dio/test/transformer_test.dart b/dio/test/transformer_test.dart index 733447c60..ab0ed8d33 100644 --- a/dio/test/transformer_test.dart +++ b/dio/test/transformer_test.dart @@ -384,6 +384,34 @@ void main() { expect(jsonResponse, null); }); + test( + 'empty JSON body with a custom responseDecoder does not throw', + () async { + // A custom decoder that returns the utf8-decoded body, which is an + // empty string for an empty response. Without guarding against an + // empty decoded string, the fused transformer would feed '' into + // jsonDecode and throw a FormatException, unlike SyncTransformer and + // BackgroundTransformer which both return an empty string here. + String decoder(List bytes, RequestOptions o, ResponseBody rb) => + utf8.decode(bytes, allowMalformed: true); + final transformer = FusedTransformer(); + final response = await transformer.transformResponse( + RequestOptions( + responseType: ResponseType.json, + responseDecoder: decoder, + ), + ResponseBody.fromBytes( + [], + 200, + headers: { + Headers.contentTypeHeader: [Headers.jsonContentType], + }, + ), + ); + expect(response, ''); + }, + ); + test('transform the request using urlencode', () async { final transformer = FusedTransformer();