From 41a5e9f0b16b6bebf92b8059e28a0b63ecdf6211 Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Mon, 30 Mar 2020 22:11:11 +1100 Subject: [PATCH] Bring Rack::Mock cookie parsing into SPEC (fixes #1629) `#has_key?` isn't required to be supported by the object in the `headers` element of the response coming back out of the app. This replaces that call with a transmogrification into a `HeaderHash` so we can use an index as normal. The odd `hash[] || ""` construction is necessary because `HeaderHash#fetch` doesn't respect header name case insensitivity. --- lib/rack/mock.rb | 28 +++++++++++++--------------- test/spec_mock.rb | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb index 5b2512ca0..f0bd0c958 100644 --- a/lib/rack/mock.rb +++ b/lib/rack/mock.rb @@ -231,21 +231,19 @@ def cookie(name) def parse_cookies_from_header cookies = Hash.new - if original_headers.has_key? 'Set-Cookie' - set_cookie_header = original_headers.fetch('Set-Cookie') - set_cookie_header.split("\n").each do |cookie| - cookie_name, cookie_filling = cookie.split('=', 2) - cookie_attributes = identify_cookie_attributes cookie_filling - parsed_cookie = CGI::Cookie.new( - 'name' => cookie_name.strip, - 'value' => cookie_attributes.fetch('value'), - 'path' => cookie_attributes.fetch('path', nil), - 'domain' => cookie_attributes.fetch('domain', nil), - 'expires' => cookie_attributes.fetch('expires', nil), - 'secure' => cookie_attributes.fetch('secure', false) - ) - cookies.store(cookie_name, parsed_cookie) - end + hashed_headers = Rack::Utils::HeaderHash[original_headers] + [hashed_headers.fetch("Set-Cookie", "")].flatten.join("\n").split("\n").each do |cookie| + cookie_name, cookie_filling = cookie.split('=', 2) + cookie_attributes = identify_cookie_attributes cookie_filling + parsed_cookie = CGI::Cookie.new( + 'name' => cookie_name.strip, + 'value' => cookie_attributes.fetch('value'), + 'path' => cookie_attributes.fetch('path', nil), + 'domain' => cookie_attributes.fetch('domain', nil), + 'expires' => cookie_attributes.fetch('expires', nil), + 'secure' => cookie_attributes.fetch('secure', false) + ) + cookies.store(cookie_name, parsed_cookie) end cookies end diff --git a/test/spec_mock.rb b/test/spec_mock.rb index d2311f5a2..4204f9ad2 100644 --- a/test/spec_mock.rb +++ b/test/spec_mock.rb @@ -324,6 +324,21 @@ res.cookie("i_dont_exist").must_be_nil end + it "parses cookie headers provided as an array" do + res = Rack::MockRequest.new(->(env) { [200, [["set-cookie", "array=awesome"]], [""]] }).get("") + array_cookie = res.cookie("array") + array_cookie.value[0].must_equal "awesome" + end + + it "parses multiple set-cookie headers provided as an array" do + cookie_headers = [["set-cookie", "array=awesome\nmultiple=times"]] + res = Rack::MockRequest.new(->(env) { [200, cookie_headers, [""]] }).get("") + array_cookie = res.cookie("array") + array_cookie.value[0].must_equal "awesome" + second_cookie = res.cookie("multiple") + second_cookie.value[0].must_equal "times" + end + it "provide access to the HTTP body" do res = Rack::MockRequest.new(app).get("") res.body.must_match(/rack/)