Skip to content

Commit 29d3262

Browse files
authored
Synchronously finalize headers (#359)
Fixes #351 An `async*` method is not started until after the stream has a listener, if a caller reads the headers before listening to the stream, they would see the value before they have been set. Move the header assignment and other finalization work to the wrapping method and keep the `async*` method handling only the stream content.
1 parent 180c77a commit 29d3262

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## 0.12.0+4-dev
22

3-
* Internal changes.
3+
* Fix a bug setting the `'content-type'` header in `MultipartRequest`.
44

55
## 0.12.0+3
66

lib/src/multipart_request.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,15 @@ class MultipartRequest extends BaseRequest {
8585
/// Freezes all mutable fields and returns a single-subscription [ByteStream]
8686
/// that will emit the request body.
8787
@override
88-
ByteStream finalize() => ByteStream(_finalize());
89-
90-
Stream<List<int>> _finalize() async* {
91-
// TODO(nweiz): freeze fields and files
92-
var boundary = _boundaryString();
88+
ByteStream finalize() {
89+
// TODO: freeze fields and files
90+
final boundary = _boundaryString();
9391
headers['content-type'] = 'multipart/form-data; boundary=$boundary';
9492
super.finalize();
93+
return ByteStream(_finalize(boundary));
94+
}
95+
96+
Stream<List<int>> _finalize(String boundary) async* {
9597
const line = [13, 10]; // \r\n
9698
final separator = utf8.encode('--$boundary\r\n');
9799
final close = utf8.encode('--$boundary--\r\n');

test/io/client_test.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
@TestOn('vm')
66

7+
import 'dart:convert';
78
import 'dart:io';
89

910
import 'package:http/http.dart' as http;
@@ -106,4 +107,18 @@ void main() {
106107
request.sink.add('{"hello": "world"}'.codeUnits);
107108
request.sink.close();
108109
});
110+
111+
test('sends a MultipartRequest with correct content-type header', () async {
112+
var client = http.Client();
113+
var request = http.MultipartRequest('POST', serverUrl);
114+
115+
var response = await client.send(request);
116+
117+
var bytesString = await response.stream.bytesToString();
118+
client.close();
119+
120+
var headers = jsonDecode(bytesString)['headers'] as Map<String, dynamic>;
121+
var contentType = (headers['content-type'] as List).single;
122+
expect(contentType, startsWith('multipart/form-data; boundary='));
123+
});
109124
}

0 commit comments

Comments
 (0)