From d3225f7c201320ed272a2fa7b000c5850e4a5f88 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 dbdb5cad7..b7ccdf964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,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")