From a577b00f9aa8ee6f6fdaae08fffe409b904be8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaudio=20Ku=C3=A7aj?= Date: Fri, 20 Dec 2024 13:59:00 +0100 Subject: [PATCH] feat: Implementing lazy parsing for common headers and updating tests --- lib/src/headers/headers.dart | 132 +++++++++++------- .../typed_headers/accept_header_test.dart | 15 ++ .../accept_ranges_header_test.dart | 15 ++ .../transfer_encoding_header_test.dart | 15 ++ 4 files changed, 127 insertions(+), 50 deletions(-) diff --git a/lib/src/headers/headers.dart b/lib/src/headers/headers.dart index 8a659f6..3544c6f 100644 --- a/lib/src/headers/headers.dart +++ b/lib/src/headers/headers.dart @@ -295,10 +295,17 @@ abstract base class Headers { _crossOriginOpenerPolicy.value; /// Common Headers (Used in Both Requests and Responses) - final AcceptHeader? accept; - final AcceptRangesHeader? acceptRanges; - final TransferEncodingHeader? transferEncoding; - final String? xPoweredBy; + final _LazyInit _accept; + AcceptHeader? get accept => _accept.value; + + final _LazyInit _acceptRanges; + AcceptRangesHeader? get acceptRanges => _acceptRanges.value; + + final _LazyInit _transferEncoding; + TransferEncodingHeader? get transferEncoding => _transferEncoding.value; + + final _LazyInit _xPoweredBy; + String? get xPoweredBy => _xPoweredBy.value; /// Custom Headers final CustomHeaders custom; @@ -467,10 +474,10 @@ abstract base class Headers { required _LazyInit crossOriginOpenerPolicy, // Common Headers (Used in Both Requests and Responses) - this.accept, - this.acceptRanges, - this.transferEncoding, - this.xPoweredBy, + required _LazyInit accept, + required _LazyInit acceptRanges, + required _LazyInit transferEncoding, + required _LazyInit xPoweredBy, // Custom Headers CustomHeaders? custom, @@ -548,6 +555,12 @@ abstract base class Headers { _crossOriginEmbedderPolicy = crossOriginEmbedderPolicy, _crossOriginOpenerPolicy = crossOriginOpenerPolicy, + // Common Headers (Used in Both Requests and Responses) + _accept = accept, + _acceptRanges = acceptRanges, + _transferEncoding = transferEncoding, + _xPoweredBy = xPoweredBy, + // Request Headers custom = custom ?? CustomHeaders.empty(); @@ -868,25 +881,6 @@ abstract base class Headers { ), ), - // Common Headers (Used in Both Requests and Responses) - accept: dartIOHeaders.parseMultipleValue( - acceptHeader, - onParse: AcceptHeader.parse, - ), - acceptRanges: dartIOHeaders.parseSingleValue( - acceptRangesHeader, - onParse: AcceptRangesHeader.parse, - ), - transferEncoding: dartIOHeaders.parseMultipleValue( - transferEncodingHeader, - onParse: TransferEncodingHeader.parse, - ), - xPoweredBy: dartIOHeaders.parseSingleValue( - xPoweredByHeader, - onParse: parseString, - ) ?? - xPoweredBy, - // Security and Modern Headers strictTransportSecurity: _LazyInit.lazy( init: () => dartIOHeaders.parseSingleValue( @@ -967,6 +961,34 @@ abstract base class Headers { ), ), + // Common Headers (Used in Both Requests and Responses) + accept: _LazyInit.lazy( + init: () => dartIOHeaders.parseMultipleValue( + acceptHeader, + onParse: AcceptHeader.parse, + ), + ), + acceptRanges: _LazyInit.lazy( + init: () => dartIOHeaders.parseSingleValue( + acceptRangesHeader, + onParse: AcceptRangesHeader.parse, + ), + ), + transferEncoding: _LazyInit.lazy( + init: () => dartIOHeaders.parseMultipleValue( + transferEncodingHeader, + onParse: TransferEncodingHeader.parse, + ), + ), + xPoweredBy: _LazyInit.lazy( + init: () => + dartIOHeaders.parseSingleValue( + xPoweredByHeader, + onParse: parseString, + ) ?? + xPoweredBy, + ), + // Custom Headers custom: parseCustomHeaders( dartIOHeaders.headers, @@ -1077,12 +1099,6 @@ abstract base class Headers { wwwAuthenticate: _LazyInit.nullValue(), contentDisposition: _LazyInit.nullValue(), - //common headers - accept: accept, - acceptRanges: acceptRanges, - transferEncoding: transferEncoding, - xPoweredBy: xPoweredBy, - // Security and Modern Headers secFetchDest: _LazyInit.value(value: secFetchDest), secFetchMode: _LazyInit.value(value: secFetchMode), @@ -1098,6 +1114,12 @@ abstract base class Headers { accessControlAllowHeaders: _LazyInit.nullValue(), clearSiteData: _LazyInit.nullValue(), + //common headers + accept: _LazyInit.value(value: accept), + acceptRanges: _LazyInit.value(value: acceptRanges), + transferEncoding: _LazyInit.value(value: transferEncoding), + xPoweredBy: _LazyInit.value(value: xPoweredBy), + // Custom headers custom: custom ?? CustomHeaders.empty(), @@ -1224,13 +1246,6 @@ abstract base class Headers { contentDisposition: _LazyInit.value(value: contentDisposition), setCookie: _LazyInit.value(value: setCookie), - //common headers - accept: accept, - acceptRanges: acceptRanges, - transferEncoding: transferEncoding, - xPoweredBy: xPoweredBy, - custom: custom ?? CustomHeaders.empty(), - // Security and Modern Headers strictTransportSecurity: _LazyInit.value(value: strictTransportSecurity), contentSecurityPolicy: _LazyInit.value(value: contentSecurityPolicy), @@ -1250,6 +1265,16 @@ abstract base class Headers { _LazyInit.value(value: crossOriginEmbedderPolicy), crossOriginOpenerPolicy: _LazyInit.value(value: crossOriginOpenerPolicy), + // Common Headers (Used in Both Requests and Responses) + accept: _LazyInit.value(value: accept), + acceptRanges: _LazyInit.value(value: acceptRanges), + transferEncoding: _LazyInit.value(value: transferEncoding), + xPoweredBy: _LazyInit.value(value: xPoweredBy), + + // Custom headers + custom: custom ?? CustomHeaders.empty(), + + // Failed headers to parse failedHeadersToParse: {}, ); } @@ -1414,10 +1439,10 @@ final class _HeadersImpl extends Headers { required super.crossOriginOpenerPolicy, /// Common Headers (Used in Both Requests and Responses) - super.accept, - super.acceptRanges, - super.transferEncoding, - super.xPoweredBy, + required super.accept, + required super.acceptRanges, + required super.transferEncoding, + required super.xPoweredBy, // Custom headers super.custom, @@ -1672,14 +1697,19 @@ final class _HeadersImpl extends Headers { : _crossOriginOpenerPolicy, /// Common Headers (Used in Both Requests and Responses) - accept: accept is AcceptHeader? ? accept : this.accept, + accept: + accept is AcceptHeader? ? _LazyInit.value(value: accept) : _accept, acceptRanges: acceptRanges is AcceptRangesHeader? - ? acceptRanges - : this.acceptRanges, + ? _LazyInit.value(value: acceptRanges) + : _acceptRanges, transferEncoding: transferEncoding is TransferEncodingHeader? - ? transferEncoding - : this.transferEncoding, - xPoweredBy: xPoweredBy is String? ? xPoweredBy : this.xPoweredBy, + ? _LazyInit.value(value: transferEncoding) + : _transferEncoding, + xPoweredBy: xPoweredBy is String? + ? _LazyInit.value(value: xPoweredBy) + : _xPoweredBy, + + // Custom headers custom: custom ?? this.custom, // Failed headers to parse @@ -1926,6 +1956,8 @@ final class _HeadersImpl extends Headers { Headers.crossOriginResourcePolicyHeader: crossOriginResourcePolicy, Headers.crossOriginEmbedderPolicyHeader: crossOriginEmbedderPolicy, Headers.crossOriginOpenerPolicyHeader: crossOriginOpenerPolicy, + Headers.acceptHeader: accept, + Headers.acceptRangesHeader: acceptRanges, }; } diff --git a/test/headers/typed_headers/accept_header_test.dart b/test/headers/typed_headers/accept_header_test.dart index 1fa8f5f..a5bf5e7 100644 --- a/test/headers/typed_headers/accept_header_test.dart +++ b/test/headers/typed_headers/accept_header_test.dart @@ -67,6 +67,21 @@ void main() { }, ); + test( + 'when an Accept header with an invalid value is passed ' + 'then the server does not respond with a bad request if the headers ' + 'is not actually used', + () async { + Headers headers = await getServerRequestHeaders( + server: server, + headers: {'accept': 'text/html;q=abc'}, + echoHeaders: false, + ); + + expect(headers, isNotNull); + }, + ); + test( 'when a valid Accept header is passed then it should parse the media types correctly', () async { diff --git a/test/headers/typed_headers/accept_ranges_header_test.dart b/test/headers/typed_headers/accept_ranges_header_test.dart index 29fa613..8144512 100644 --- a/test/headers/typed_headers/accept_ranges_header_test.dart +++ b/test/headers/typed_headers/accept_ranges_header_test.dart @@ -48,6 +48,21 @@ void main() { }, ); + test( + 'when an Accept-Ranges header with an empty value is passed ' + 'then the server does not respond with a bad request if the headers ' + 'is not actually used', + () async { + Headers headers = await getServerRequestHeaders( + server: server, + headers: {'accept-ranges': ''}, + echoHeaders: false, + ); + + expect(headers, isNotNull); + }, + ); + test( 'when a valid Accept-Ranges header is passed then it should parse the range unit correctly', () async { diff --git a/test/headers/typed_headers/transfer_encoding_header_test.dart b/test/headers/typed_headers/transfer_encoding_header_test.dart index e583645..5ae7328 100644 --- a/test/headers/typed_headers/transfer_encoding_header_test.dart +++ b/test/headers/typed_headers/transfer_encoding_header_test.dart @@ -66,6 +66,21 @@ void main() { }, ); + test( + 'when a Transfer-Encoding header with an invalid value is passed ' + 'then the server does not respond with a bad request if the headers ' + 'is not actually used', + () async { + Headers headers = await getServerRequestHeaders( + server: server, + headers: {'transfer-encoding': 'custom-encoding'}, + echoHeaders: false, + ); + + expect(headers, isNotNull); + }, + ); + test( 'when a valid Transfer-Encoding header is passed then it should parse the encodings correctly', () async {