From 89ad78c1336c0c324d2163b0fd61389fb89e2585 Mon Sep 17 00:00:00 2001 From: Seven Du <5564821+medz@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:58:03 +0800 Subject: [PATCH 1/4] Fix RFC 850 two-digit year parsing --- pkgs/http_parser/CHANGELOG.md | 1 + pkgs/http_parser/lib/src/http_date.dart | 6 ++++-- pkgs/http_parser/test/http_date_test.dart | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkgs/http_parser/CHANGELOG.md b/pkgs/http_parser/CHANGELOG.md index befc949355..1e74a54b31 100644 --- a/pkgs/http_parser/CHANGELOG.md +++ b/pkgs/http_parser/CHANGELOG.md @@ -1,5 +1,6 @@ ## 4.1.3-wip +* Apply the RFC 9110 50-year rule when parsing RFC 850 dates. * Replace reference to `dart:web` with `package:web` in README.md. ## 4.1.2 diff --git a/pkgs/http_parser/lib/src/http_date.dart b/pkgs/http_parser/lib/src/http_date.dart index 0cedd9a6d8..e8d9171260 100644 --- a/pkgs/http_parser/lib/src/http_date.dart +++ b/pkgs/http_parser/lib/src/http_date.dart @@ -55,7 +55,7 @@ String formatHttpDate(DateTime date) { /// Parses an HTTP-formatted date into a UTC [DateTime]. /// -/// This follows [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). +/// This follows [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.7). /// It will throw a [FormatException] if [date] is invalid. DateTime parseHttpDate(String date) => wrapFormatException('HTTP date', date, () { @@ -68,7 +68,9 @@ DateTime parseHttpDate(String date) => scanner.expect('-'); final month = _parseMonth(scanner); scanner.expect('-'); - final year = 1900 + _parseInt(scanner, 2); + final currentYear = DateTime.now().toUtc().year; + var year = currentYear - currentYear % 100 + _parseInt(scanner, 2); + if (year > currentYear + 50) year -= 100; scanner.expect(' '); final time = _parseTime(scanner); scanner.expect(' GMT'); diff --git a/pkgs/http_parser/test/http_date_test.dart b/pkgs/http_parser/test/http_date_test.dart index d117663f50..6b1c90587d 100644 --- a/pkgs/http_parser/test/http_date_test.dart +++ b/pkgs/http_parser/test/http_date_test.dart @@ -155,6 +155,13 @@ void main() { expect(date.timeZoneName, equals('UTC')); }); + test('applies the two-digit year rule', () { + expect( + parseHttpDate('Sunday, 21-Jun-26 07:28:00 GMT'), + DateTime.utc(2026, DateTime.june, 21, 7, 28), + ); + }); + test('whitespace is required', () { expect(() => parseHttpDate('Sunday,06-Nov-94 08:49:37 GMT'), throwsFormatException); From 988c0877b2304adeab5831a65a75ecde5fc70dd0 Mon Sep 17 00:00:00 2001 From: Seven Du <5564821+medz@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:39:44 +0800 Subject: [PATCH 2/4] Update pkgs/http_parser/lib/src/http_date.dart Co-authored-by: Brian Quinlan --- pkgs/http_parser/lib/src/http_date.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/http_parser/lib/src/http_date.dart b/pkgs/http_parser/lib/src/http_date.dart index e8d9171260..0fe55fad2d 100644 --- a/pkgs/http_parser/lib/src/http_date.dart +++ b/pkgs/http_parser/lib/src/http_date.dart @@ -68,6 +68,11 @@ DateTime parseHttpDate(String date) => scanner.expect('-'); final month = _parseMonth(scanner); scanner.expect('-'); + // RFC 9110, Section 5.6.7 says: + // Recipients of a timestamp value in rfc850-date format, which uses a + // two-digit year, MUST interpret a timestamp that appears to be more + // than 50 years in the future as representing the most recent year in the + // past that had the same last two digits. final currentYear = DateTime.now().toUtc().year; var year = currentYear - currentYear % 100 + _parseInt(scanner, 2); if (year > currentYear + 50) year -= 100; From db6ff3e949394aea1e3a67886cdcd597a1a83065 Mon Sep 17 00:00:00 2001 From: Seven Du <5564821+medz@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:41:17 +0800 Subject: [PATCH 3/4] Clarify RFC 850 parsing change --- pkgs/http_parser/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/http_parser/CHANGELOG.md b/pkgs/http_parser/CHANGELOG.md index 1e74a54b31..6036418978 100644 --- a/pkgs/http_parser/CHANGELOG.md +++ b/pkgs/http_parser/CHANGELOG.md @@ -1,6 +1,8 @@ ## 4.1.3-wip -* Apply the RFC 9110 50-year rule when parsing RFC 850 dates. +* **BREAKING:** Apply the RFC 9110 50-year rule when parsing RFC 850 dates. + Previously, two-digit years were always interpreted as years between 1900 + and 1999. * Replace reference to `dart:web` with `package:web` in README.md. ## 4.1.2 From 09df9d9b77c490299d440603ed13adc4c37738f3 Mon Sep 17 00:00:00 2001 From: Seven Du <5564821+medz@users.noreply.github.com> Date: Tue, 4 Aug 2026 13:29:52 +0800 Subject: [PATCH 4/4] Fix RFC 850 comment lint --- pkgs/http_parser/lib/src/http_date.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/http_parser/lib/src/http_date.dart b/pkgs/http_parser/lib/src/http_date.dart index 0fe55fad2d..d7f04ad5f6 100644 --- a/pkgs/http_parser/lib/src/http_date.dart +++ b/pkgs/http_parser/lib/src/http_date.dart @@ -71,8 +71,8 @@ DateTime parseHttpDate(String date) => // RFC 9110, Section 5.6.7 says: // Recipients of a timestamp value in rfc850-date format, which uses a // two-digit year, MUST interpret a timestamp that appears to be more - // than 50 years in the future as representing the most recent year in the - // past that had the same last two digits. + // than 50 years in the future as representing the most recent year + // in the past that had the same last two digits. final currentYear = DateTime.now().toUtc().year; var year = currentYear - currentYear % 100 + _parseInt(scanner, 2); if (year > currentYear + 50) year -= 100;