Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Ensure multiple values for the same header can be recorded and played…

… back.

This already worked for most adapters, but had an issue for the HTTP client adapter.

Note that I had to change the line breaks in the webmock server response to \r\n (which matches the HTTP spec, I believe) in order to get curb and patron to parse the headers correctly.
  • Loading branch information...
commit 553496851cebbef505708c91f99ae1d00151a9d6 1 parent 7c21556
Myron Marston authored February 18, 2012
12  lib/webmock/http_lib_adapters/httpclient_adapter.rb
@@ -112,7 +112,17 @@ def build_httpclient_response(webmock_response, stream = false, &block)
112 112
   def build_webmock_response(httpclient_response)
113 113
     webmock_response = WebMock::Response.new
114 114
     webmock_response.status = [httpclient_response.status, httpclient_response.reason]
115  
-    webmock_response.headers = httpclient_response.header.all
  115
+
  116
+    webmock_response.headers = {}.tap do |hash|
  117
+      httpclient_response.header.all.each do |(key, value)|
  118
+        if hash.has_key?(key)
  119
+          hash[key] = Array(hash[key]) + [value]
  120
+        else
  121
+          hash[key] = value
  122
+        end
  123
+      end
  124
+    end
  125
+
116 126
     if  httpclient_response.content.respond_to?(:read)
117 127
       webmock_response.body = httpclient_response.content.read
118 128
       body = HTTP::Message::Body.new
10  spec/acceptance/curb/curb_spec_helper.rb
@@ -10,6 +10,16 @@ def http_request(method, uri, options = {}, &block)
10 10
     status, response_headers =
11 11
      WebMock::HttpLibAdapters::CurbAdapter.parse_header_string(curl.header_str)
12 12
 
  13
+    # Deal with the fact that the HTTP spec allows multi-values headers
  14
+    # to either be a single entry with a comma-separated listed of
  15
+    # values, or multiple separate entries
  16
+    response_headers.keys.each do |k|
  17
+      v = response_headers[k]
  18
+      if v.is_a?(Array)
  19
+        response_headers[k] = v.join(', ')
  20
+      end
  21
+    end
  22
+
13 23
     OpenStruct.new(
14 24
       :body => curl.body_str,
15 25
       :headers => WebMock::Util::Headers.normalize_headers(response_headers),
21  spec/acceptance/shared/complex_cross_concern_behaviors.rb
... ...
@@ -0,0 +1,21 @@
  1
+shared_context "complex cross-concern behaviors" do |*adapter_info|
  2
+  it 'allows a response with multiple values for the same header to be recorded and played back exactly as-is' do
  3
+    WebMock.allow_net_connect!
  4
+
  5
+    recorded_response = nil
  6
+    WebMock.after_request { |_,r| recorded_response = r }
  7
+    real_response = http_request(:get, webmock_server_url)
  8
+
  9
+    stub_request(:get, webmock_server_url).to_return(
  10
+      :status => recorded_response.status,
  11
+      :body => recorded_response.body,
  12
+      :headers => recorded_response.headers
  13
+    )
  14
+
  15
+    played_back_response = http_request(:get, webmock_server_url)
  16
+
  17
+    played_back_response.headers.keys.should include('Set-Cookie')
  18
+    played_back_response.should == real_response
  19
+  end
  20
+end
  21
+
3  spec/acceptance/webmock_shared.rb
@@ -6,6 +6,7 @@
6 6
 require 'acceptance/shared/stubbing_requests'
7 7
 require 'acceptance/shared/allowing_and_disabling_net_connect'
8 8
 require 'acceptance/shared/precedence_of_stubs'
  9
+require 'acceptance/shared/complex_cross_concern_behaviors'
9 10
 
10 11
 unless defined? SAMPLE_HEADERS
11 12
   SAMPLE_HEADERS = { "Content-Length" => "8888", "Accept" => "application/json" }
@@ -34,5 +35,7 @@
34 35
     include_context "callbacks", *adapter_info
35 36
 
36 37
     include_context "enabled and disabled webmock", *adapter_info
  38
+
  39
+    include_context "complex cross-concern behaviors", *adapter_info
37 40
   end
38 41
 end
12  spec/support/webmock_server.rb
@@ -33,11 +33,13 @@ def start
33 33
       end
34 34
       server.start do |socket|
35 35
         socket.puts <<-EOT.gsub(/^\s+\|/, '')
36  
-          |HTTP/1.1 200 OK
37  
-          |Date: Fri, 31 Dec 1999 23:59:59 GMT
38  
-          |Content-Type: text/html
39  
-          |Content-Length: 11
40  
-          |
  36
+          |HTTP/1.1 200 OK\r
  37
+          |Date: Fri, 31 Dec 1999 23:59:59 GMT\r
  38
+          |Content-Type: text/html\r
  39
+          |Content-Length: 11\r
  40
+          |Set-Cookie: bar\r
  41
+          |Set-Cookie: foo\r
  42
+          |\r
41 43
           |hello world
42 44
         EOT
43 45
       end

0 notes on commit 5534968

Please sign in to comment.
Something went wrong with that request. Please try again.