From 193ad5c63e9fe33fa1fd827de566d7cc9c47839f Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 10:53:05 -0700 Subject: [PATCH 01/16] Only set the charset when the body is set for certain mime types --- pkgs/http/lib/src/request.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index b7e56ab559..a1f934bdbc 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -106,7 +106,9 @@ class Request extends BaseRequest { var contentType = _contentType; if (contentType == null) { _contentType = MediaType('text', 'plain', {'charset': encoding.name}); - } else if (!contentType.parameters.containsKey('charset')) { + } else if ((contentType.type == 'text' || + contentType.mimeType == 'application/xml') && + !contentType.parameters.containsKey('charset')) { _contentType = contentType.change(parameters: {'charset': encoding.name}); } } From 61591de9accb981561250636ee85cd5943909992 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 13:46:50 -0700 Subject: [PATCH 02/16] Update request.dart --- pkgs/http/lib/src/request.dart | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index a1f934bdbc..b7b800e10a 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -93,21 +93,37 @@ class Request extends BaseRequest { /// This is converted to and from [bodyBytes] using [encoding]. /// /// When this is set, if the request does not yet have a `Content-Type` - /// header, one will be added with the type `text/plain`. Then the `charset` - /// parameter of the `Content-Type` header (whether new or pre-existing) will - /// be set to [encoding] if it wasn't already set. + /// header, one will be added with the type `text/plain` and appropriate + /// `charset` parameter. /// - /// To set the body of the request, without setting the `Content-Type` header, - /// use [bodyBytes]. + /// If request has `Content-Type` header with MIME media type name `text` or + /// is an XML MIME type (e.g. `application/xml` or `image/svg+xml) but + /// without `charset` parameter, then the `charset` parameter will be set to + /// [encoding]. + /// + /// To set the body of the request, without changing the `Content-Type` + /// header, use [bodyBytes]. String get body => encoding.decode(bodyBytes); set body(String value) { + // IANA defines known media types here: + // https://www.iana.org/assignments/media-types/media-types.xhtml bodyBytes = encoding.encode(value); var contentType = _contentType; if (contentType == null) { _contentType = MediaType('text', 'plain', {'charset': encoding.name}); } else if ((contentType.type == 'text' || - contentType.mimeType == 'application/xml') && + // XML media types defined by RFC 7303. + // Note that some media types (e.g. cda+xml) specify that the + // charset, when present, must be utf-8. + contentType.mimeType == 'application/xml' || + contentType.mimeType == 'application/xml-external-parsed-entity' || + contentType.mimeType == 'application/xml-dtd' || + contentType.mimeType.endsWith('+xml')) && + // RFC 8259, 9 says that "charset" is not defined for JSON. + // Some non-text, non-xml formats do specify charset + // (e.g. application/news-checkgroups) but the user will have to set the + // charset themselves if those cases. !contentType.parameters.containsKey('charset')) { _contentType = contentType.change(parameters: {'charset': encoding.name}); } From 3f2497651ad56b65de1bb840a601027cb6654340 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 14:42:44 -0700 Subject: [PATCH 03/16] More stuff --- pkgs/http/lib/src/request.dart | 26 ++++++++----- pkgs/http/test/io/http_test.dart | 12 ++---- pkgs/http/test/request_test.dart | 38 ++++++++----------- pkgs/http/test/stub_server.dart | 18 ++++++--- .../lib/src/request_body_tests.dart | 8 ++-- 5 files changed, 51 insertions(+), 51 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index b7b800e10a..8cc70573f4 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -61,7 +61,8 @@ class Request extends BaseRequest { _checkFinalized(); _defaultEncoding = value; var contentType = _contentType; - if (contentType == null) return; + if (contentType == null || !contentType.parameters.containsKey('charset')) + return; _contentType = contentType.change(parameters: {'charset': value.name}); } @@ -105,6 +106,20 @@ class Request extends BaseRequest { /// header, use [bodyBytes]. String get body => encoding.decode(bodyBytes); + bool _should(MediaType? contentType) => (contentType != null && + // RFC 8259, 9 says that "charset" is not defined for JSON. + // Some non-text, non-xml formats do specify charset + // (e.g. application/news-checkgroups) but the user will have to set the + // charset themselves if those cases. + (contentType.type == 'text' || + // XML media types defined by RFC 7303. + // Note that some media types (e.g. cda+xml) specify that the + // charset, when present, must be utf-8. + contentType.mimeType == 'application/xml' || + contentType.mimeType == 'application/xml-external-parsed-entity' || + contentType.mimeType == 'application/xml-dtd' || + contentType.mimeType.endsWith('+xml'))); + set body(String value) { // IANA defines known media types here: // https://www.iana.org/assignments/media-types/media-types.xhtml @@ -112,14 +127,7 @@ class Request extends BaseRequest { var contentType = _contentType; if (contentType == null) { _contentType = MediaType('text', 'plain', {'charset': encoding.name}); - } else if ((contentType.type == 'text' || - // XML media types defined by RFC 7303. - // Note that some media types (e.g. cda+xml) specify that the - // charset, when present, must be utf-8. - contentType.mimeType == 'application/xml' || - contentType.mimeType == 'application/xml-external-parsed-entity' || - contentType.mimeType == 'application/xml-dtd' || - contentType.mimeType.endsWith('+xml')) && + } else if (_should(_contentType) && // RFC 8259, 9 says that "charset" is not defined for JSON. // Some non-text, non-xml formats do specify charset // (e.g. application/news-checkgroups) but the user will have to set the diff --git a/pkgs/http/test/io/http_test.dart b/pkgs/http/test/io/http_test.dart index 3f9aad815e..d4c19bd987 100644 --- a/pkgs/http/test/io/http_test.dart +++ b/pkgs/http/test/io/http_test.dart @@ -158,9 +158,7 @@ void main() { 'method': 'POST', 'path': '/', 'headers': { - 'content-type': [ - 'application/x-www-form-urlencoded; charset=utf-8' - ], + 'content-type': ['application/x-www-form-urlencoded'], 'content-length': ['40'], 'accept-encoding': ['gzip'], 'user-agent': ['Dart'], @@ -273,9 +271,7 @@ void main() { 'method': 'PUT', 'path': '/', 'headers': { - 'content-type': [ - 'application/x-www-form-urlencoded; charset=utf-8' - ], + 'content-type': ['application/x-www-form-urlencoded'], 'content-length': ['40'], 'accept-encoding': ['gzip'], 'user-agent': ['Dart'], @@ -388,9 +384,7 @@ void main() { 'method': 'PATCH', 'path': '/', 'headers': { - 'content-type': [ - 'application/x-www-form-urlencoded; charset=utf-8' - ], + 'content-type': ['application/x-www-form-urlencoded'], 'content-length': ['40'], 'accept-encoding': ['gzip'], 'user-agent': ['Dart'], diff --git a/pkgs/http/test/request_test.dart b/pkgs/http/test/request_test.dart index 59cb0988c5..19cccfe272 100644 --- a/pkgs/http/test/request_test.dart +++ b/pkgs/http/test/request_test.dart @@ -189,23 +189,12 @@ void main() { expect(request.headers, containsPair('content-type', 'application/json')); }); - test( - 'is set to application/x-www-form-urlencoded with charset utf-8 if ' - 'bodyFields is set', () { - var request = http.Request('POST', dummyUrl) - ..bodyFields = {'hello': 'world'}; - expect(request.headers['Content-Type'], - equals('application/x-www-form-urlencoded; charset=utf-8')); - }); - - test( - 'is set to application/x-www-form-urlencoded with the given charset ' - 'if bodyFields and encoding are set', () { + test('is set to application/x-www-form-urlencoded if bodyFields is set', + () { var request = http.Request('POST', dummyUrl) - ..encoding = latin1 ..bodyFields = {'hello': 'world'}; expect(request.headers['Content-Type'], - equals('application/x-www-form-urlencoded; charset=iso-8859-1')); + equals('application/x-www-form-urlencoded')); }); test( @@ -218,20 +207,25 @@ void main() { equals('text/plain; charset=iso-8859-1')); }); - test('is modified to include utf-8 if body is set', () { + test('is modified to include utf-8 if body is set and mine type is text', + () { var request = http.Request('POST', dummyUrl); - request.headers['Content-Type'] = 'application/json'; + request.headers['Content-Type'] = 'text/plain'; request.body = '{"hello": "world"}'; - expect(request.headers['Content-Type'], - equals('application/json; charset=utf-8')); + expect( + request.headers['Content-Type'], equals('text/plain; charset=utf-8')); }); - test('is modified to include the given encoding if encoding is set', () { + test( + 'is modified to include the given encoding if encoding is set and ' + 'mine type is text', () { var request = http.Request('POST', dummyUrl); - request.headers['Content-Type'] = 'application/json'; - request.encoding = latin1; + request.headers['Content-Type'] = 'text/plain'; + request + ..body = 'Hello World!' + ..encoding = latin1; expect(request.headers['Content-Type'], - equals('application/json; charset=iso-8859-1')); + equals('text/plain; charset=iso-8859-1')); }); test('has its charset overridden by an explicit encoding', () { diff --git a/pkgs/http/test/stub_server.dart b/pkgs/http/test/stub_server.dart index a53f77d375..366d505d66 100644 --- a/pkgs/http/test/stub_server.dart +++ b/pkgs/http/test/stub_server.dart @@ -65,14 +65,20 @@ void hybridMain(StreamChannel channel) async { dynamic requestBody; if (requestBodyBytes.isEmpty) { requestBody = null; - } else if (request.headers.contentType?.charset != null) { - var encoding = - requiredEncodingForCharset(request.headers.contentType!.charset!); - requestBody = encoding.decode(requestBodyBytes); } else { - requestBody = requestBodyBytes; + requestBody = switch (( + request.headers.contentType?.mimeType, + request.headers.contentType?.charset + )) { + (_, var charset?) => + requiredEncodingForCharset(charset).decode(requestBodyBytes), + // This is not a complete set of mime types that default to utf-8, + // just the ones found in the tests. + ('application/json' || 'application/x-www-form-urlencoded', null) => + utf8.decode(requestBodyBytes), + _ => requestBodyBytes, + }; } - final headers = >{}; request.headers.forEach((name, values) { diff --git a/pkgs/http_client_conformance_tests/lib/src/request_body_tests.dart b/pkgs/http_client_conformance_tests/lib/src/request_body_tests.dart index 98da3785a3..2af53c6e78 100644 --- a/pkgs/http_client_conformance_tests/lib/src/request_body_tests.dart +++ b/pkgs/http_client_conformance_tests/lib/src/request_body_tests.dart @@ -78,8 +78,7 @@ void testRequestBody(Client client) { final serverReceivedContentType = await httpServerQueue.next; final serverReceivedBody = await httpServerQueue.next; - expect(serverReceivedContentType, - ['application/x-www-form-urlencoded; charset=utf-8']); + expect(serverReceivedContentType, ['application/x-www-form-urlencoded']); expect(serverReceivedBody, 'key=value'); }); @@ -90,8 +89,7 @@ void testRequestBody(Client client) { final serverReceivedContentType = await httpServerQueue.next; final serverReceivedBody = await httpServerQueue.next; - expect(serverReceivedContentType, - ['application/x-www-form-urlencoded; charset=plus2']); + expect(serverReceivedContentType, ['application/x-www-form-urlencoded']); expect(serverReceivedBody, 'gau;r]hqa'); // key=value }); @@ -149,7 +147,7 @@ void testRequestBody(Client client) { final serverReceivedContentType = await httpServerQueue.next; final serverReceivedBody = await httpServerQueue.next as String; - expect(serverReceivedContentType, ['image/png; charset=plus2']); + expect(serverReceivedContentType, ['image/png']); expect(serverReceivedBody.codeUnits, [1, 2, 3, 4, 5]); }); From c3a6cb21505c5024496aa48ba957a9ad976384a3 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 14:47:48 -0700 Subject: [PATCH 04/16] Update request.dart --- pkgs/http/lib/src/request.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index 8cc70573f4..3ecdfd07f5 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -61,8 +61,9 @@ class Request extends BaseRequest { _checkFinalized(); _defaultEncoding = value; var contentType = _contentType; - if (contentType == null || !contentType.parameters.containsKey('charset')) + if (contentType == null || !contentType.parameters.containsKey('charset')) { return; + } _contentType = contentType.change(parameters: {'charset': value.name}); } @@ -106,7 +107,8 @@ class Request extends BaseRequest { /// header, use [bodyBytes]. String get body => encoding.decode(bodyBytes); - bool _should(MediaType? contentType) => (contentType != null && + bool _should(MediaType? contentType) => + contentType != null && // RFC 8259, 9 says that "charset" is not defined for JSON. // Some non-text, non-xml formats do specify charset // (e.g. application/news-checkgroups) but the user will have to set the @@ -118,7 +120,7 @@ class Request extends BaseRequest { contentType.mimeType == 'application/xml' || contentType.mimeType == 'application/xml-external-parsed-entity' || contentType.mimeType == 'application/xml-dtd' || - contentType.mimeType.endsWith('+xml'))); + contentType.mimeType.endsWith('+xml')); set body(String value) { // IANA defines known media types here: From e9580abdba669224ced417b8db2568ef6160c8ba Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 15:36:44 -0700 Subject: [PATCH 05/16] Pubspec --- pkgs/cronet_http/example/pubspec.yaml | 3 +-- pkgs/cupertino_http/example/pubspec.yaml | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/cronet_http/example/pubspec.yaml b/pkgs/cronet_http/example/pubspec.yaml index 87c8234218..4011e765ff 100644 --- a/pkgs/cronet_http/example/pubspec.yaml +++ b/pkgs/cronet_http/example/pubspec.yaml @@ -30,8 +30,7 @@ dev_dependencies: flutter: uses-material-design: true -# TODO(brianquinlan): Remove this when a release version of `package:http` -# supports abortable requests. +# Use the checked-in version of `package:http` for consistency with tests. dependency_overrides: http: path: ../../http/ diff --git a/pkgs/cupertino_http/example/pubspec.yaml b/pkgs/cupertino_http/example/pubspec.yaml index 38f75b0cf9..fca91327b5 100644 --- a/pkgs/cupertino_http/example/pubspec.yaml +++ b/pkgs/cupertino_http/example/pubspec.yaml @@ -38,3 +38,8 @@ dev_dependencies: flutter: uses-material-design: true + +# Use the checked-in version of `package:http` for consistency with tests +dependency_overrides: + http: + path: ../../http/ From 89b23d852bc7445d6b14b5b1852f7e79ba6641b2 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 15:50:00 -0700 Subject: [PATCH 06/16] Update request.dart --- pkgs/http/lib/src/request.dart | 37 ++++++++++++++++------------------ 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index 3ecdfd07f5..d5f10d5bfc 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -14,6 +14,22 @@ import 'utils.dart'; /// An HTTP request where the entire request body is known in advance. class Request extends BaseRequest { + /// Whether the given MIME type should have a 'charset' parameter. + bool _shouldHaveCharset(MediaType? contentType) => + contentType != null && + // RFC 8259, 9 says that "charset" is not defined for JSON. + // Some non-text, non-xml formats do specify charset + // (e.g. application/news-checkgroups) but the user will have to set the + // charset themselves if those cases. + (contentType.type == 'text' || + // XML media types defined by RFC 7303. + // Note that some media types (e.g. cda+xml) specify that the + // charset, when present, must be utf-8. + contentType.mimeType == 'application/xml' || + contentType.mimeType == 'application/xml-external-parsed-entity' || + contentType.mimeType == 'application/xml-dtd' || + contentType.mimeType.endsWith('+xml')); + /// The size of the request body, in bytes. This is calculated from /// [bodyBytes]. /// @@ -107,21 +123,6 @@ class Request extends BaseRequest { /// header, use [bodyBytes]. String get body => encoding.decode(bodyBytes); - bool _should(MediaType? contentType) => - contentType != null && - // RFC 8259, 9 says that "charset" is not defined for JSON. - // Some non-text, non-xml formats do specify charset - // (e.g. application/news-checkgroups) but the user will have to set the - // charset themselves if those cases. - (contentType.type == 'text' || - // XML media types defined by RFC 7303. - // Note that some media types (e.g. cda+xml) specify that the - // charset, when present, must be utf-8. - contentType.mimeType == 'application/xml' || - contentType.mimeType == 'application/xml-external-parsed-entity' || - contentType.mimeType == 'application/xml-dtd' || - contentType.mimeType.endsWith('+xml')); - set body(String value) { // IANA defines known media types here: // https://www.iana.org/assignments/media-types/media-types.xhtml @@ -129,11 +130,7 @@ class Request extends BaseRequest { var contentType = _contentType; if (contentType == null) { _contentType = MediaType('text', 'plain', {'charset': encoding.name}); - } else if (_should(_contentType) && - // RFC 8259, 9 says that "charset" is not defined for JSON. - // Some non-text, non-xml formats do specify charset - // (e.g. application/news-checkgroups) but the user will have to set the - // charset themselves if those cases. + } else if (_shouldHaveCharset(_contentType) && !contentType.parameters.containsKey('charset')) { _contentType = contentType.change(parameters: {'charset': encoding.name}); } From 45223d904e1c9ea4a74cef2990309c30a29006d1 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 15:58:59 -0700 Subject: [PATCH 07/16] Update request.dart --- pkgs/http/lib/src/request.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index d5f10d5bfc..0cf5691537 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -17,10 +17,10 @@ class Request extends BaseRequest { /// Whether the given MIME type should have a 'charset' parameter. bool _shouldHaveCharset(MediaType? contentType) => contentType != null && - // RFC 8259, 9 says that "charset" is not defined for JSON. - // Some non-text, non-xml formats do specify charset + // RFC 8259, section 9 says that "charset" is not defined for JSON. + // Some uncommon non-text, non-xml types do specify charset // (e.g. application/news-checkgroups) but the user will have to set the - // charset themselves if those cases. + // charset themselves for those types. (contentType.type == 'text' || // XML media types defined by RFC 7303. // Note that some media types (e.g. cda+xml) specify that the From c883c1b6cd2c2d20adf4f6634d88c3db5dc320e1 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 16:06:30 -0700 Subject: [PATCH 08/16] Update request_test.dart --- pkgs/http/test/request_test.dart | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pkgs/http/test/request_test.dart b/pkgs/http/test/request_test.dart index 19cccfe272..025e770cd8 100644 --- a/pkgs/http/test/request_test.dart +++ b/pkgs/http/test/request_test.dart @@ -211,11 +211,29 @@ void main() { () { var request = http.Request('POST', dummyUrl); request.headers['Content-Type'] = 'text/plain'; - request.body = '{"hello": "world"}'; + request.body = 'Hello World!'; expect( request.headers['Content-Type'], equals('text/plain; charset=utf-8')); }); + test('is modified to include utf-8 if body is set and mine type is xml', + () { + var request = http.Request('POST', dummyUrl); + request.headers['Content-Type'] = 'application/xml'; + request.body = ' Date: Thu, 24 Jul 2025 16:43:12 -0700 Subject: [PATCH 09/16] CHANGELOG --- pkgs/http/CHANGELOG.md | 5 +++++ pkgs/http/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/http/CHANGELOG.md b/pkgs/http/CHANGELOG.md index 80d9110d3e..7f91ff5aea 100644 --- a/pkgs/http/CHANGELOG.md +++ b/pkgs/http/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.5.0-beta.3 + +* **Breaking** Change the behavior of `Request.body` so that a charset + parameter is only added for text and XML media types. + ## 1.5.0-beta.2 * Fixed a bug in `IOClient` where the `HttpClient`'s response stream was diff --git a/pkgs/http/pubspec.yaml b/pkgs/http/pubspec.yaml index 442b6b991c..56fa6f447e 100644 --- a/pkgs/http/pubspec.yaml +++ b/pkgs/http/pubspec.yaml @@ -1,5 +1,5 @@ name: http -version: 1.5.0-beta.2 +version: 1.5.0-beta.3 description: A composable, multi-platform, Future-based API for HTTP requests. repository: https://github.com/dart-lang/http/tree/master/pkgs/http From fc2df93142af8529c808682dd1bbca9df89077d2 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 24 Jul 2025 16:47:53 -0700 Subject: [PATCH 10/16] Update request.dart --- pkgs/http/lib/src/request.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index 0cf5691537..ae3c0d61bf 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -115,8 +115,8 @@ class Request extends BaseRequest { /// `charset` parameter. /// /// If request has `Content-Type` header with MIME media type name `text` or - /// is an XML MIME type (e.g. `application/xml` or `image/svg+xml) but - /// without `charset` parameter, then the `charset` parameter will be set to + /// is an XML MIME type (e.g. `application/xml` or `image/svg+xml`) without + /// `charset` parameter, then the `charset` parameter will be set to /// [encoding]. /// /// To set the body of the request, without changing the `Content-Type` From 7c1f2d933437b36aa5363e843a410e900e115860 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Fri, 8 Aug 2025 14:44:39 -0700 Subject: [PATCH 11/16] Docs --- pkgs/cupertino_http/example/pubspec.yaml | 3 ++- pkgs/ok_http/example/pubspec.yaml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/cupertino_http/example/pubspec.yaml b/pkgs/cupertino_http/example/pubspec.yaml index fca91327b5..2ee3fba734 100644 --- a/pkgs/cupertino_http/example/pubspec.yaml +++ b/pkgs/cupertino_http/example/pubspec.yaml @@ -39,7 +39,8 @@ dev_dependencies: flutter: uses-material-design: true -# Use the checked-in version of `package:http` for consistency with tests +# Use the path version of `package:http` so that the behavior matches the +# expectations in http_client_conformance_tests. dependency_overrides: http: path: ../../http/ diff --git a/pkgs/ok_http/example/pubspec.yaml b/pkgs/ok_http/example/pubspec.yaml index 873d9aaa5c..319c5faf5d 100644 --- a/pkgs/ok_http/example/pubspec.yaml +++ b/pkgs/ok_http/example/pubspec.yaml @@ -36,8 +36,8 @@ flutter: assets: - test_certs/ # Used in integration tests. -# TODO(brianquinlan): Remove this when a release version of `package:http` -# supports abortable requests. +# Use the path version of `package:http` so that the behavior matches the +# expectations in http_client_conformance_tests. dependency_overrides: http: path: ../../http/ From f02d8250b78237452b2a6b6c3a2ef240182c0914 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Fri, 8 Aug 2025 15:50:31 -0700 Subject: [PATCH 12/16] Update pubspec.yaml --- pkgs/http_client_conformance_tests/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/http_client_conformance_tests/pubspec.yaml b/pkgs/http_client_conformance_tests/pubspec.yaml index 60f8a2fd7f..aaabb793f5 100644 --- a/pkgs/http_client_conformance_tests/pubspec.yaml +++ b/pkgs/http_client_conformance_tests/pubspec.yaml @@ -11,11 +11,10 @@ environment: dependencies: async: ^2.8.2 dart_style: ">=2.3.7 <4.0.0" - http: ^1.2.0 + http: ">=1.2.0 <3.0.0" # XXX stream_channel: ^2.1.1 test: ^1.21.2 -# TODO(brianquinlan): Remove dependency_overrides when package:http 1.5.0 is released. dependency_overrides: http: path: ../http From a9c002d857325498202ba35060dd774b209c7cbb Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Fri, 8 Aug 2025 17:11:13 -0700 Subject: [PATCH 13/16] Update request_test.dart --- pkgs/http/test/request_test.dart | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/pkgs/http/test/request_test.dart b/pkgs/http/test/request_test.dart index 025e770cd8..a02d0b5820 100644 --- a/pkgs/http/test/request_test.dart +++ b/pkgs/http/test/request_test.dart @@ -207,7 +207,7 @@ void main() { equals('text/plain; charset=iso-8859-1')); }); - test('is modified to include utf-8 if body is set and mine type is text', + test('is modified to include utf-8 if body is set and mime type is text', () { var request = http.Request('POST', dummyUrl); request.headers['Content-Type'] = 'text/plain'; @@ -216,7 +216,7 @@ void main() { request.headers['Content-Type'], equals('text/plain; charset=utf-8')); }); - test('is modified to include utf-8 if body is set and mine type is xml', + test('is modified to include utf-8 if body is set and mime type is xml', () { var request = http.Request('POST', dummyUrl); request.headers['Content-Type'] = 'application/xml'; @@ -226,7 +226,7 @@ void main() { }); test( - 'is not modified to include utf-8 if body is set and mine type is json', + 'is not modified to include utf-8 if body is set and mime type is json', () { var request = http.Request('POST', dummyUrl); request.headers['Content-Type'] = 'application/json'; @@ -236,7 +236,7 @@ void main() { test( 'is modified to include the given encoding if encoding is set and ' - 'mine type is text', () { + 'mime type is text', () { var request = http.Request('POST', dummyUrl); request.headers['Content-Type'] = 'text/plain'; request @@ -246,6 +246,29 @@ void main() { equals('text/plain; charset=iso-8859-1')); }); + test( + 'is modified to include the given encoding if encoding is set and ' + 'mime type is xml', () { + var request = http.Request('POST', dummyUrl); + request.headers['Content-Type'] = 'application/xml'; + request + ..body = ' Date: Mon, 11 Aug 2025 10:35:29 -0700 Subject: [PATCH 14/16] Fix --- pkgs/http/lib/src/request.dart | 2 +- pkgs/http_client_conformance_tests/pubspec.yaml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index ae3c0d61bf..0c856b0dbd 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -24,7 +24,7 @@ class Request extends BaseRequest { (contentType.type == 'text' || // XML media types defined by RFC 7303. // Note that some media types (e.g. cda+xml) specify that the - // charset, when present, must be utf-8. + // charset, when present, must be utf-8. We do not enforce this. contentType.mimeType == 'application/xml' || contentType.mimeType == 'application/xml-external-parsed-entity' || contentType.mimeType == 'application/xml-dtd' || diff --git a/pkgs/http_client_conformance_tests/pubspec.yaml b/pkgs/http_client_conformance_tests/pubspec.yaml index aaabb793f5..9f644c55c5 100644 --- a/pkgs/http_client_conformance_tests/pubspec.yaml +++ b/pkgs/http_client_conformance_tests/pubspec.yaml @@ -11,7 +11,9 @@ environment: dependencies: async: ^2.8.2 dart_style: ">=2.3.7 <4.0.0" - http: ">=1.2.0 <3.0.0" # XXX + # TODO(brianquinlan): Tighten this version constraint when package:http 2.0 + # is released. + http: ">=1.2.0 <3.0.0" stream_channel: ^2.1.1 test: ^1.21.2 From f0979abeb9549c663f30a1075b4d7d8e218e58da Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Wed, 17 Sep 2025 10:36:57 -0700 Subject: [PATCH 15/16] Change version --- pkgs/http/CHANGELOG.md | 5 +++-- pkgs/http/pubspec.yaml | 2 +- pkgs/http_client_conformance_tests/pubspec.yaml | 4 +--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/http/CHANGELOG.md b/pkgs/http/CHANGELOG.md index b3bc7e031f..4c0c31af84 100644 --- a/pkgs/http/CHANGELOG.md +++ b/pkgs/http/CHANGELOG.md @@ -1,7 +1,8 @@ -## 2.0.0-wip +## 1.6.0-wip * **Breaking** Change the behavior of `Request.body` so that a charset - parameter is only added for text and XML media types. + parameter is only added for text and XML media types. This brings the + behavior of `package:http` in line with RFC-8259. ## 1.5.0 diff --git a/pkgs/http/pubspec.yaml b/pkgs/http/pubspec.yaml index 9760b4685e..da0bb24e88 100644 --- a/pkgs/http/pubspec.yaml +++ b/pkgs/http/pubspec.yaml @@ -1,5 +1,5 @@ name: http -version: 2.0.0-wip +version: 1.6.0-wip description: A composable, multi-platform, Future-based API for HTTP requests. repository: https://github.com/dart-lang/http/tree/master/pkgs/http diff --git a/pkgs/http_client_conformance_tests/pubspec.yaml b/pkgs/http_client_conformance_tests/pubspec.yaml index 9f644c55c5..dd566b8798 100644 --- a/pkgs/http_client_conformance_tests/pubspec.yaml +++ b/pkgs/http_client_conformance_tests/pubspec.yaml @@ -11,9 +11,7 @@ environment: dependencies: async: ^2.8.2 dart_style: ">=2.3.7 <4.0.0" - # TODO(brianquinlan): Tighten this version constraint when package:http 2.0 - # is released. - http: ">=1.2.0 <3.0.0" + http: ^1.2.0 stream_channel: ^2.1.1 test: ^1.21.2 From dd602435a946d7b67e62bc5acd7b21b2ae5e50d1 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 18 Sep 2025 07:57:58 -0700 Subject: [PATCH 16/16] Make `_shouldHaveCharset` `static` --- pkgs/http/lib/src/request.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/http/lib/src/request.dart b/pkgs/http/lib/src/request.dart index 0c856b0dbd..41bd130d15 100644 --- a/pkgs/http/lib/src/request.dart +++ b/pkgs/http/lib/src/request.dart @@ -15,7 +15,7 @@ import 'utils.dart'; /// An HTTP request where the entire request body is known in advance. class Request extends BaseRequest { /// Whether the given MIME type should have a 'charset' parameter. - bool _shouldHaveCharset(MediaType? contentType) => + static bool _shouldHaveCharset(MediaType? contentType) => contentType != null && // RFC 8259, section 9 says that "charset" is not defined for JSON. // Some uncommon non-text, non-xml types do specify charset