diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index 178710516..0c2d1e7dc 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -116,7 +116,7 @@ class IOHttpClientAdapter implements HttpClientAdapter { request.headers.set( key, value, - preserveHeaderCase: !options.caseInsensitiveHeaders, + preserveHeaderCase: options.caseSensitiveHeaders, ); } }); diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index 89f20fd70..936faa80f 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -517,7 +517,10 @@ abstract class DioMixin implements Dio { stream, cancelToken?.whenCancel, ); - final headers = Headers.fromMap(responseBody.headers); + final headers = Headers.fromMap( + responseBody.headers, + caseSensitive: reqOpt.caseSensitiveHeaders, + ); // Make sure headers and [ResponseBody.headers] are the same instance. responseBody.headers = headers.map; final ret = Response( @@ -707,7 +710,10 @@ abstract class DioMixin implements Dio { final T? data = response.data as T?; final Headers headers; if (data is ResponseBody) { - headers = Headers.fromMap(data.headers); + headers = Headers.fromMap( + data.headers, + caseSensitive: requestOptions.caseSensitiveHeaders, + ); } else { headers = response.headers; } diff --git a/dio/lib/src/headers.dart b/dio/lib/src/headers.dart index 2b1873731..07cfd3118 100644 --- a/dio/lib/src/headers.dart +++ b/dio/lib/src/headers.dart @@ -8,13 +8,13 @@ typedef HeaderForEachCallback = void Function(String name, List values); /// The headers class for requests and responses. class Headers { Headers({ - this.caseInsensitive = true, + this.caseSensitive = false, }) : _map = caseInsensitiveKeyMap>(); /// Create the [Headers] from a [Map] instance. Headers.fromMap( Map> map, { - this.caseInsensitive = true, + this.caseSensitive = false, }) : _map = caseInsensitiveKeyMap>( map.map((k, v) => MapEntry(k.trim(), v)), ); @@ -32,10 +32,10 @@ class Headers { static final jsonMimeType = MediaType.parse(jsonContentType); - /// Whether the header key should be case-insensitive. + /// Whether the header key should be case-sensitive. /// - /// Defaults to true. - final bool caseInsensitive; + /// Defaults to false. + final bool caseSensitive; final Map> _map; @@ -44,9 +44,6 @@ class Headers { /// Returns the list of values for the header named [name]. If there /// is no header with the provided name, [:null:] will be returned. List? operator [](String name) { - if (caseInsensitive) { - name = name.toLowerCase(); - } return _map[name.trim()]; } @@ -75,9 +72,6 @@ class Headers { /// cleared before the value [value] is added as its value. void set(String name, dynamic value) { if (value == null) return; - if (caseInsensitive) { - name = name.toLowerCase(); - } name = name.trim(); if (value is List) { _map[name] = value.map((e) => '$e').toList(); diff --git a/dio/lib/src/options.dart b/dio/lib/src/options.dart index 8206c130a..bcc0c5858 100644 --- a/dio/lib/src/options.dart +++ b/dio/lib/src/options.dart @@ -128,7 +128,7 @@ class BaseOptions extends _RequestConfig with OptionsMixin { Map? queryParameters, Map? extra, Map? headers, - bool? caseInsensitiveHeaders, + bool caseSensitiveHeaders = false, ResponseType? responseType = ResponseType.json, String? contentType, ValidateStatus? validateStatus, @@ -147,7 +147,7 @@ class BaseOptions extends _RequestConfig with OptionsMixin { sendTimeout: sendTimeout, extra: extra, headers: headers, - caseInsensitiveHeaders: caseInsensitiveHeaders, + caseSensitiveHeaders: caseSensitiveHeaders, responseType: responseType, contentType: contentType, validateStatus: validateStatus, @@ -175,7 +175,7 @@ class BaseOptions extends _RequestConfig with OptionsMixin { Duration? sendTimeout, Map? extra, Map? headers, - bool? caseInsensitiveHeaders, + bool? caseSensitiveHeaders, ResponseType? responseType, String? contentType, ValidateStatus? validateStatus, @@ -196,8 +196,8 @@ class BaseOptions extends _RequestConfig with OptionsMixin { sendTimeout: sendTimeout ?? this.sendTimeout, extra: extra ?? Map.from(this.extra), headers: headers ?? Map.from(this.headers), - caseInsensitiveHeaders: - caseInsensitiveHeaders ?? this.caseInsensitiveHeaders, + caseSensitiveHeaders: + caseSensitiveHeaders ?? this.caseSensitiveHeaders, responseType: responseType ?? this.responseType, contentType: contentType ?? this.contentType, validateStatus: validateStatus ?? this.validateStatus, @@ -221,7 +221,7 @@ class Options { Duration? receiveTimeout, this.extra, this.headers, - this.caseInsensitiveHeaders, + this.caseSensitiveHeaders, this.responseType, this.contentType, this.validateStatus, @@ -244,7 +244,7 @@ class Options { Duration? receiveTimeout, Map? extra, Map? headers, - bool? caseInsensitiveHeaders, + bool? caseSensitiveHeaders, ResponseType? responseType, String? contentType, ValidateStatus? validateStatus, @@ -281,8 +281,8 @@ class Options { receiveTimeout: receiveTimeout ?? this.receiveTimeout, extra: extra ?? effectiveExtra, headers: headers ?? effectiveHeaders, - caseInsensitiveHeaders: - caseInsensitiveHeaders ?? this.caseInsensitiveHeaders, + caseSensitiveHeaders: + caseSensitiveHeaders ?? this.caseSensitiveHeaders, responseType: responseType ?? this.responseType, contentType: contentType ?? this.contentType, validateStatus: validateStatus ?? this.validateStatus, @@ -331,8 +331,8 @@ class Options { baseUrl: baseOpt.baseUrl, path: path, data: data, - caseInsensitiveHeaders: - caseInsensitiveHeaders ?? baseOpt.caseInsensitiveHeaders, + caseSensitiveHeaders: + caseSensitiveHeaders ?? baseOpt.caseSensitiveHeaders, sourceStackTrace: sourceStackTrace ?? StackTrace.current, connectTimeout: baseOpt.connectTimeout, sendTimeout: sendTimeout ?? baseOpt.sendTimeout, @@ -367,15 +367,14 @@ class Options { /// e.g.: `content-type` and `Content-Type` will be treated as the same key. Map? headers; - /// Whether the header keys should be case-insensitive. - /// e.g.: `Content-Type` will be sent as `content-type` eventually. + /// Whether the header keys should be case-sensitive. /// - /// Defaults to true. + /// Defaults to false. /// /// This option WILL NOT take effect on these circumstances: /// - XHR ([HttpRequest]) does not support handling this explicitly. /// - The HTTP/2 standard only supports lowercase header keys. - bool? caseInsensitiveHeaders; + bool? caseSensitiveHeaders; /// Timeout when sending data. /// @@ -493,7 +492,7 @@ class RequestOptions extends _RequestConfig with OptionsMixin { String? baseUrl, Map? extra, Map? headers, - bool caseInsensitiveHeaders = true, + bool? caseSensitiveHeaders, ResponseType? responseType, String? contentType, ValidateStatus? validateStatus, @@ -513,7 +512,7 @@ class RequestOptions extends _RequestConfig with OptionsMixin { receiveTimeout: receiveTimeout, extra: extra, headers: headers, - caseInsensitiveHeaders: caseInsensitiveHeaders, + caseSensitiveHeaders: caseSensitiveHeaders, responseType: responseType, contentType: contentType, validateStatus: validateStatus, @@ -546,7 +545,7 @@ class RequestOptions extends _RequestConfig with OptionsMixin { CancelToken? cancelToken, Map? extra, Map? headers, - bool? caseInsensitiveHeaders, + bool? caseSensitiveHeaders, ResponseType? responseType, String? contentType, ValidateStatus? validateStatus, @@ -583,8 +582,8 @@ class RequestOptions extends _RequestConfig with OptionsMixin { cancelToken: cancelToken ?? this.cancelToken, extra: extra ?? Map.from(this.extra), headers: headers ?? Map.from(this.headers), - caseInsensitiveHeaders: - caseInsensitiveHeaders ?? this.caseInsensitiveHeaders, + caseSensitiveHeaders: + caseSensitiveHeaders ?? this.caseSensitiveHeaders, responseType: responseType ?? this.responseType, validateStatus: validateStatus ?? this.validateStatus, receiveDataWhenStatusError: @@ -662,7 +661,7 @@ class _RequestConfig { String? method, Map? extra, Map? headers, - bool? caseInsensitiveHeaders, + bool? caseSensitiveHeaders, String? contentType, ListFormat? listFormat, bool? followRedirects, @@ -678,7 +677,7 @@ class _RequestConfig { assert(sendTimeout == null || !sendTimeout.isNegative), _sendTimeout = sendTimeout, method = method ?? 'GET', - caseInsensitiveHeaders = caseInsensitiveHeaders ?? true, + caseSensitiveHeaders = caseSensitiveHeaders ?? false, listFormat = listFormat ?? ListFormat.multi, extra = extra ?? {}, followRedirects = followRedirects ?? true, @@ -718,7 +717,7 @@ class _RequestConfig { } } - late bool caseInsensitiveHeaders; + late bool caseSensitiveHeaders; Duration? get sendTimeout => _sendTimeout; Duration? _sendTimeout; diff --git a/dio/lib/src/response.dart b/dio/lib/src/response.dart index b6ff998de..9760ad082 100644 --- a/dio/lib/src/response.dart +++ b/dio/lib/src/response.dart @@ -19,7 +19,8 @@ class Response { this.redirects = const [], Map? extra, Headers? headers, - }) : headers = headers ?? Headers(), + }) : headers = headers ?? + Headers(caseSensitive: requestOptions.caseSensitiveHeaders), extra = extra ?? {}; /// The response payload in specific type. diff --git a/dio/test/basic_test.dart b/dio/test/basic_test.dart index e21506dcb..ccb6ea79c 100644 --- a/dio/test/basic_test.dart +++ b/dio/test/basic_test.dart @@ -48,9 +48,11 @@ void main() { 'content-length': ['200'], 'Test': ['1', '2'], }, - caseInsensitive: false, + caseSensitive: true, ); expect(headers['SET-COOKIE']?.length, 2); + // Although it's case-sensitive, we still use case-insensitive map. + expect(headers['set-cookie']?.length, 2); expect(headers['content-length']?.length, 1); expect(headers['Test']?.length, 2); });