@@ -42,86 +42,97 @@ class SyncTransformer extends Transformer {
42
42
}
43
43
}
44
44
45
- /// As an agreement, we return the [response] when the
46
- /// Options.responseType is [ResponseType.stream] .
47
45
@override
48
46
Future <dynamic > transformResponse (
49
47
RequestOptions options,
50
- ResponseBody response ,
48
+ ResponseBody responseBody ,
51
49
) async {
50
+ final responseType = options.responseType;
51
+ // Do not handled the body for streams.
52
52
if (options.responseType == ResponseType .stream) {
53
- return response ;
53
+ return responseBody ;
54
54
}
55
- int length = 0 ;
56
- int received = 0 ;
55
+
57
56
final showDownloadProgress = options.onReceiveProgress != null ;
57
+ final int totalLength;
58
58
if (showDownloadProgress) {
59
- length = int .parse (
60
- response .headers[Headers .contentLengthHeader]? .first ?? '-1' ,
59
+ totalLength = int .parse (
60
+ responseBody .headers[Headers .contentLengthHeader]? .first ?? '-1' ,
61
61
);
62
+ } else {
63
+ totalLength = 0 ;
62
64
}
63
- final completer = Completer ();
64
- final stream = response.stream.transform <Uint8List >(
65
+
66
+ int received = 0 ;
67
+ final stream = responseBody.stream.transform <Uint8List >(
65
68
StreamTransformer .fromHandlers (
66
69
handleData: (data, sink) {
67
70
sink.add (data);
68
71
if (showDownloadProgress) {
69
72
received += data.length;
70
- options.onReceiveProgress? .call (received, length );
73
+ options.onReceiveProgress? .call (received, totalLength );
71
74
}
72
75
},
73
76
),
74
77
);
78
+
79
+ final streamCompleter = Completer <void >();
80
+ int finalLength = 0 ;
75
81
// Keep references to the data chunks and concatenate them later.
76
82
final chunks = < Uint8List > [];
77
- int finalSize = 0 ;
78
- final StreamSubscription subscription = stream.listen (
83
+ final subscription = stream.listen (
79
84
(chunk) {
80
- finalSize += chunk.length;
85
+ finalLength += chunk.length;
81
86
chunks.add (chunk);
82
87
},
83
88
onError: (Object error, StackTrace stackTrace) {
84
- completer.completeError (error, stackTrace);
89
+ streamCompleter.completeError (error, stackTrace);
90
+ },
91
+ onDone: () {
92
+ streamCompleter.complete ();
85
93
},
86
- onDone: () => completer.complete (),
87
94
cancelOnError: true ,
88
95
);
89
96
options.cancelToken? .whenCancel.then ((_) {
90
97
return subscription.cancel ();
91
98
});
92
- await completer.future;
93
- // Copy all chunks into a final Uint8List.
94
- final responseBytes = Uint8List (finalSize);
99
+ await streamCompleter.future;
100
+
101
+ // Copy all chunks into the final bytes.
102
+ final responseBytes = Uint8List (finalLength);
95
103
int chunkOffset = 0 ;
96
104
for (final chunk in chunks) {
97
105
responseBytes.setAll (chunkOffset, chunk);
98
106
chunkOffset += chunk.length;
99
107
}
100
108
101
- if (options.responseType == ResponseType .bytes) {
109
+ // Return the finalized bytes if the response type is bytes.
110
+ if (responseType == ResponseType .bytes) {
102
111
return responseBytes;
103
112
}
104
113
105
- final String ? responseBody;
114
+ final isJsonContent = Transformer .isJsonMimeType (
115
+ responseBody.headers[Headers .contentTypeHeader]? .first,
116
+ );
117
+ final String ? response;
106
118
if (options.responseDecoder != null ) {
107
- responseBody = options.responseDecoder !(
119
+ response = options.responseDecoder !(
108
120
responseBytes,
109
121
options,
110
- response ..stream = Stream .empty (),
122
+ responseBody ..stream = Stream .empty (),
111
123
);
112
- } else if (responseBytes.isNotEmpty) {
113
- responseBody = utf8.decode (responseBytes, allowMalformed: true );
124
+ } else if (! isJsonContent || responseBytes.isNotEmpty) {
125
+ response = utf8.decode (responseBytes, allowMalformed: true );
114
126
} else {
115
- responseBody = null ;
127
+ response = null ;
116
128
}
117
- if (responseBody != null &&
118
- responseBody.isNotEmpty &&
119
- options.responseType == ResponseType .json &&
120
- Transformer .isJsonMimeType (
121
- response.headers[Headers .contentTypeHeader]? .first,
122
- )) {
123
- return jsonDecodeCallback (responseBody);
129
+
130
+ if (response != null &&
131
+ response.isNotEmpty &&
132
+ responseType == ResponseType .json &&
133
+ isJsonContent) {
134
+ return jsonDecodeCallback (response);
124
135
}
125
- return responseBody ;
136
+ return response ;
126
137
}
127
138
}
0 commit comments