diff options
author | Robin Wallin <walro467@gmail.com> | 2021-11-14 22:16:07 +0100 |
---|---|---|
committer | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2022-01-25 17:57:20 +1300 |
commit | a411e18b00fe58187eb95dd1479878631f3a7473 (patch) | |
tree | a38b7b373e06d0411483224432645fd8c912ebae | |
parent | f1583d47f695a1799fb568bb57f2c3687d2fd40c (diff) | |
download | rack-a411e18b00fe58187eb95dd1479878631f3a7473.tar.gz |
Properly set the expires attribute for the mock response cookie
Prior to this change, cookies with the `Expires` attribute would have the attribute stored as a `String` object rather than a `Time` object. `CGI::Cookie` expects a `Time` object [1]. Having strings could lead to confusing errors later on. For example, calling `Rack::MockResponse#inspect` would lead to `undefined method `gmtime' for "Fri, 03 Jun 2022 19:37:33 GMT":String`. As per RFC 6265, if a cookie has both the `Max-Age` and the `Expires` attribute, `Max-Age` has precedence. [2] Close #1758 [1]: https://ruby-doc.org/stdlib-3.0.1/libdoc/cgi/rdoc/CGI/Cookie.html [2]: https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.2.2
-rw-r--r-- | lib/rack/mock.rb | 11 | ||||
-rw-r--r-- | test/spec_mock.rb | 23 |
2 files changed, 30 insertions, 4 deletions
diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb index 184e3cbb..33339117 100644 --- a/lib/rack/mock.rb +++ b/lib/rack/mock.rb @@ -4,6 +4,7 @@ require 'uri' require 'stringio' require_relative '../rack' require 'cgi/cookie' +require 'time' module Rack # Rack::MockRequest helps testing your Rack application without @@ -260,14 +261,18 @@ module Rack if bit.include? '=' cookie_attribute, attribute_value = bit.split('=', 2) cookie_attributes.store(cookie_attribute.strip, attribute_value.strip) - if cookie_attribute.include? 'max-age' - cookie_attributes.store('expires', Time.now + attribute_value.strip.to_i) - end end if bit.include? 'secure' cookie_attributes.store('secure', true) end end + + if cookie_attributes.key? 'max-age' + cookie_attributes.store('expires', Time.now + cookie_attributes['max-age'].to_i) + elsif cookie_attributes.key? 'expires' + cookie_attributes.store('expires', Time.httpdate(cookie_attributes['expires'])) + end + cookie_attributes end diff --git a/test/spec_mock.rb b/test/spec_mock.rb index 08e3a457..e81f8d83 100644 --- a/test/spec_mock.rb +++ b/test/spec_mock.rb @@ -30,6 +30,8 @@ app = Rack::Lint.new(lambda { |env| response.set_cookie("session_test", { value: "session_test", domain: ".test.com", path: "/" }) response.set_cookie("secure_test", { value: "secure_test", domain: ".test.com", path: "/", secure: true }) response.set_cookie("persistent_test", { value: "persistent_test", max_age: 15552000, path: "/" }) + response.set_cookie("persistent_with_expires_test", { value: "persistent_with_expires_test", expires: Time.httpdate("Thu, 31 Oct 2021 07:28:00 GMT"), path: "/" }) + response.set_cookie("expires_and_max-age_test", { value: "expires_and_max-age_test", expires: Time.now + 15552000 * 2, max_age: 15552000, path: "/" }) response.finish }) @@ -307,7 +309,7 @@ describe Rack::MockResponse do session_cookie.expires.must_be_nil end - it "provide access to persistent cookies" do + it "provides access to persistent cookies set with max-age" do res = Rack::MockRequest.new(app).get("") persistent_cookie = res.cookie("persistent_test") persistent_cookie.value[0].must_equal "persistent_test" @@ -318,6 +320,25 @@ describe Rack::MockResponse do persistent_cookie.expires.must_be :<, (Time.now + 15552000) end + it "provides access to persistent cookies set with expires" do + res = Rack::MockRequest.new(app).get("") + persistent_cookie = res.cookie("persistent_with_expires_test") + persistent_cookie.value[0].must_equal "persistent_with_expires_test" + persistent_cookie.domain.must_be_nil + persistent_cookie.path.must_equal "/" + persistent_cookie.secure.must_equal false + persistent_cookie.expires.wont_be_nil + persistent_cookie.expires.must_equal Time.httpdate("Thu, 31 Oct 2021 07:28:00 GMT") + end + + it "parses cookies giving max-age precedence over expires" do + res = Rack::MockRequest.new(app).get("") + persistent_cookie = res.cookie("expires_and_max-age_test") + persistent_cookie.value[0].must_equal "expires_and_max-age_test" + persistent_cookie.expires.wont_be_nil + persistent_cookie.expires.must_be :<, (Time.now + 15552000) + end + it "provide access to secure cookies" do res = Rack::MockRequest.new(app).get("") secure_cookie = res.cookie("secure_test") |