From 16350bc4b27bcecfa7bc04d989008c811488ffb9 Mon Sep 17 00:00:00 2001 From: James Reeves Date: Fri, 8 Mar 2024 20:08:31 +0000 Subject: [PATCH] Fix cookie date timezone format Cookie timezones now always 'GMT', as specified by RFC2616. This RFC is obsoleted by RFC6265, which has more permissive datetime parsing, but in the interests of backward-compatibility, we should adhere to the older RFC. Fixes #349. --- ring-core/src/ring/middleware/cookies.clj | 10 ++++++++-- ring-core/test/ring/middleware/test/cookies.clj | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ring-core/src/ring/middleware/cookies.clj b/ring-core/src/ring/middleware/cookies.clj index c082cb9a..057ce001 100644 --- a/ring-core/src/ring/middleware/cookies.clj +++ b/ring-core/src/ring/middleware/cookies.clj @@ -60,13 +60,19 @@ (try (Class/forName s) (catch ClassNotFoundException _))) +;; RFC2616 requires a 'GMT' timezone, and while this is obsoleted by RFC6262, +;; which is more permissive in its parsing, in order to be as backward- +;; compatible as possible, we'll use a fixed 'GMT' timezone, which in this +;; case is equivalent to UTC. +(def ^:private datetime-format "EEE, dd MMM yyyy HH:mm:ss 'GMT'") + (when-let [dt (class-by-name "org.joda.time.DateTime")] (extend dt CookieDateTime {:rfc822-format (eval '(let [fmtr (.. (org.joda.time.format.DateTimeFormat/forPattern - "EEE, dd MMM yyyy HH:mm:ss Z") + datetime-format) (withZone org.joda.time.DateTimeZone/UTC) (withLocale java.util.Locale/US))] (fn [interval] @@ -84,7 +90,7 @@ (.get this ChronoUnit/SECONDS))) (let [java-rfc822-formatter - (.. (DateTimeFormatter/ofPattern "EEE, dd MMM yyyy HH:mm:ss Z") + (.. (DateTimeFormatter/ofPattern datetime-format) (withZone (ZoneId/of "UTC")) (withLocale Locale/US))] (extend-protocol CookieDateTime diff --git a/ring-core/test/ring/middleware/test/cookies.clj b/ring-core/test/ring/middleware/test/cookies.clj index 4463f28e..bb1a7579 100644 --- a/ring-core/test/ring/middleware/test/cookies.clj +++ b/ring-core/test/ring/middleware/test/cookies.clj @@ -205,7 +205,7 @@ :expires (date-time 2015 12 31)}} handler (constantly {:cookies cookies}) resp ((wrap-cookies handler) {}) - expires "Thu, 31 Dec 2015 00:00:00 +0000"] + expires "Thu, 31 Dec 2015 00:00:00 GMT"] (is (= {"Set-Cookie" #{"a=b" "Path=/" "Secure" "HttpOnly" (str "Expires=" expires)}} (split-set-cookie (:headers resp)))))) @@ -215,7 +215,7 @@ :expires (zoned-date-time 2015 12 31)}} handler (constantly {:cookies cookies}) resp ((wrap-cookies handler) {}) - expires "Thu, 31 Dec 2015 00:00:00 +0000"] + expires "Thu, 31 Dec 2015 00:00:00 GMT"] (is (= {"Set-Cookie" #{"a=b" "Path=/" "Secure" "HttpOnly" (str "Expires=" expires)}} (split-set-cookie (:headers resp)))))) @@ -228,7 +228,7 @@ :expires (date-time 2015 12 31)}} handler (constantly {:cookies cookies}) resp ((wrap-cookies handler) {}) - expires "Thu, 31 Dec 2015 00:00:00 +0000"] + expires "Thu, 31 Dec 2015 00:00:00 GMT"] (is (= {"Set-Cookie" #{"a=b" "Path=/" "Secure" "HttpOnly" (str "Expires=" expires)}} (split-set-cookie (:headers resp))))) (finally @@ -243,7 +243,7 @@ :expires (zoned-date-time 2015 12 31)}} handler (constantly {:cookies cookies}) resp ((wrap-cookies handler) {}) - expires "Thu, 31 Dec 2015 00:00:00 +0000"] + expires "Thu, 31 Dec 2015 00:00:00 GMT"] (is (= {"Set-Cookie" #{"a=b" "Path=/" "Secure" "HttpOnly" (str "Expires=" expires)}} (split-set-cookie (:headers resp))))) (finally