From 30ecc6c33dcc3315907bcbe30d52abb59ce6af5e Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 14 Jul 2020 09:04:36 -0700 Subject: [PATCH] Make Rack::MockResponse handle non-hash headers Rack::MockResponse inherits from Rack::Response, which already uses a HeaderHash for the headers. The original_headers were only used for cookie parsing, which for some reason was happening before the call to super in initialize (so the headers weren't available yet). There seems to be no reason why the cookie parsing can't happen after the call to super, in which case we can use the headers directly. Fixes #1629 Fixes #1630 Co-authored-by: Matt Palmer --- CHANGELOG.md | 1 + lib/rack/mock.rb | 6 +++--- test/spec_mock.rb | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f024e744..157864f7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. For info on ### Fixed +- Make Rack::MockResponse handle non-hash headers. ([#1629](https://github.com/rack/rack/issues/1629), [@jeremyevans](https://github.com/jeremyevans)) - TempfileReaper now deletes temp files if application raises an exception. ([#1679](https://github.com/rack/rack/issues/1679), [@jeremyevans](https://github.com/jeremyevans)) - Fix using Rack::Session::Cookie with coder: Rack::Session::Cookie::Base64::{JSON,Zip}. ([#1666](https://github.com/rack/rack/issues/1666), [@jeremyevans](https://github.com/jeremyevans)) - Avoid NoMethodError when accessing Rack::Session::Cookie without requiring delegate first. ([#1610](https://github.com/rack/rack/issues/1610), [@onigra](https://github.com/onigra)) diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb index f330ae18f..14ee7f0bc 100644 --- a/lib/rack/mock.rb +++ b/lib/rack/mock.rb @@ -184,10 +184,10 @@ class << self def initialize(status, headers, body, errors = StringIO.new("")) @original_headers = headers @errors = errors.string if errors.respond_to?(:string) - @cookies = parse_cookies_from_header super(body, status, headers) + @cookies = parse_cookies_from_header buffered_body! end @@ -231,8 +231,8 @@ 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') + if headers.has_key? 'Set-Cookie' + set_cookie_header = 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 diff --git a/test/spec_mock.rb b/test/spec_mock.rb index 43fd07d19..bce1cd201 100644 --- a/test/spec_mock.rb +++ b/test/spec_mock.rb @@ -330,6 +330,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/) @@ -346,6 +361,12 @@ res.errors.must_include "foo" end + it "handle enumerable headers that are not a hash" do + # this is exactly what rack-test does + res = Rack::MockResponse.new(200, [], []) + res.cookies.must_equal({}) + end + it "allow calling body.close afterwards" do # this is exactly what rack-test does body = StringIO.new("hi")