net.http.request_response_uri.2.patch

Currently you can't use a Net::HTTPRequest for multiple hosts since the Host header is filled in, so my patch matches current behavior. - Eric Hodel, 06/07/2012 10:02 AM

Download (14.1 KB)

View differences:

lib/net/http/response.rb (working copy)
132 132
    initialize_http_header nil
133 133
    @body = nil
134 134
    @read = false
135
    @uri  = nil
135 136
  end
136 137

  
137 138
  # The HTTP version supported by the server.
......
146 147
  attr_reader :message
147 148
  alias msg message   # :nodoc: obsolete
148 149

  
150
  # The URI used to fetch this response.  The response URI is only available
151
  # if a URI was used to create the request.
152
  attr_reader :uri
153

  
149 154
  def inspect
150 155
    "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
151 156
  end
......
171 176
    error! unless self.kind_of?(Net::HTTPSuccess)
172 177
  end
173 178

  
179
  def uri= uri # :nodoc:
180
    @uri = uri.dup if uri
181
  end
182

  
174 183
  #
175 184
  # header (for backward compatibility only; DO NOT USE)
176 185
  #
lib/net/http/generic_request.rb (working copy)
7 7

  
8 8
  include Net::HTTPHeader
9 9

  
10
  def initialize(m, reqbody, resbody, path, initheader = nil)
10
  def initialize(m, reqbody, resbody, uri_or_path, initheader = nil)
11 11
    @method = m
12 12
    @request_has_body = reqbody
13 13
    @response_has_body = resbody
14

  
15
    if URI === uri_or_path then
16
      @uri = uri_or_path.dup
17
      host = uri.host
18
      host << ":#{uri.port}" if uri.port != uri.class::DEFAULT_PORT
19
      path = uri_or_path.request_uri
20
    else
21
      @uri = nil
22
      host = nil
23
      path = uri_or_path
24
    end
25

  
14 26
    raise ArgumentError, "no HTTP request path given" unless path
15 27
    raise ArgumentError, "HTTP request path is empty" if path.empty?
16 28
    @path = path
17 29
    initialize_http_header initheader
18 30
    self['Accept'] ||= '*/*'
19 31
    self['User-Agent'] ||= 'Ruby'
32
    self['Host'] ||= host
20 33
    @body = nil
21 34
    @body_stream = nil
22 35
    @body_data = nil
......
24 37

  
25 38
  attr_reader :method
26 39
  attr_reader :path
40
  attr_reader :uri
27 41

  
28 42
  def inspect
29 43
    "\#<#{self.class} #{@method}>"
......
81 95
    end
82 96
  end
83 97

  
98
  def update_uri(host, port, ssl) # :nodoc: internal use only
99
    return unless @uri
100

  
101
    @uri.host = host
102
    @uri.port = port
103

  
104
    scheme = ssl ? 'https' : 'http'
105

  
106
    # convert the class of the URI
107
    unless scheme == @uri.scheme then
108
      new_uri = @uri.to_s.sub(/^https?/, scheme)
109
      @uri = URI new_uri
110
    end
111

  
112
    @uri
113
  end
114

  
84 115
  private
85 116

  
86 117
  class Chunker #:nodoc:
lib/net/http.rb (working copy)
93 93
  #   uri = URI('http://example.com/some_path?query=string')
94 94
  #
95 95
  #   Net::HTTP.start(uri.host, uri.port) do |http|
96
  #     request = Net::HTTP::Get.new uri.request_uri
96
  #     request = Net::HTTP::Get.new uri
97 97
  #
98 98
  #     response = http.request request # Net::HTTPResponse object
99 99
  #   end
......
111 111
  # will automatically open a connection to the server if one is not currently
112 112
  # open.  You can manually close the connection with #finish.
113 113
  #
114
  # For all the Net::HTTP request objects and shortcut request methods you may
115
  # supply either a String for the request path or a URI from which Net::HTTP
116
  # will extract the request path.
117
  #
114 118
  # === Response Data
115 119
  #
116 120
  #   uri = URI('http://example.com/index.html')
......
168 172
  # creates a urlencoded POST body:
169 173
  #
170 174
  #   uri = URI('http://www.example.com/todo.cgi')
171
  #   req = Net::HTTP::Post.new(uri.path)
175
  #   req = Net::HTTP::Post.new(uri)
172 176
  #   req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')
173 177
  #
174 178
  #   res = Net::HTTP.start(uri.hostname, uri.port) do |http|
......
186 190
  # multipart/form-data use Net::HTTPRequest#body= and
187 191
  # Net::HTTPRequest#content_type=:
188 192
  #
189
  #   req = Net::HTTP::Post.new(uri.path)
193
  #   req = Net::HTTP::Post.new(uri)
190 194
  #   req.body = multipart_data
191 195
  #   req.content_type = 'multipart/form-data'
192 196
  #
......
203 207
  #   uri = URI('http://example.com/cached_response')
204 208
  #   file = File.stat 'cached_response'
205 209
  #
206
  #   req = Net::HTTP::Get.new(uri.request_uri)
210
  #   req = Net::HTTP::Get.new(uri)
207 211
  #   req['If-Modified-Since'] = file.mtime.rfc2822
208 212
  #
209 213
  #   res = Net::HTTP.start(uri.hostname, uri.port) {|http|
......
221 225
  #
222 226
  #   uri = URI('http://example.com/index.html?key=value')
223 227
  #
224
  #   req = Net::HTTP::Get.new(uri.request_uri)
228
  #   req = Net::HTTP::Get.new(uri)
225 229
  #   req.basic_auth 'user', 'pass'
226 230
  #
227 231
  #   res = Net::HTTP.start(uri.hostname, uri.port) {|http|
......
238 242
  #   uri = URI('http://example.com/large_file')
239 243
  #
240 244
  #   Net::HTTP.start(uri.host, uri.port) do |http|
241
  #     request = Net::HTTP::Get.new uri.request_uri
245
  #     request = Net::HTTP::Get.new uri
242 246
  #
243 247
  #     http.request request do |response|
244 248
  #       open 'large_file', 'w' do |io|
......
257 261
  #
258 262
  #   Net::HTTP.start(uri.host, uri.port,
259 263
  #     :use_ssl => uri.scheme == 'https') do |http|
260
  #     request = Net::HTTP::Get.new uri.request_uri
264
  #     request = Net::HTTP::Get.new uri
261 265
  #
262 266
  #     response = http.request request # Net::HTTPResponse object
263 267
  #   end
......
453 457
        uri = uri_or_host
454 458
        start(uri.hostname, uri.port,
455 459
              :use_ssl => uri.scheme == 'https') {|http|
456
          return http.request_get(uri.request_uri, &block)
460
          return http.request_get(uri, &block)
457 461
        }
458 462
      end
459 463
    end
......
477 481
    #                  { "q" => "ruby", "max" => "50" }
478 482
    #
479 483
    def HTTP.post_form(url, params)
480
      req = Post.new(url.request_uri)
484
      req = Post.new(url)
481 485
      req.form_data = params
482 486
      req.basic_auth url.user, url.password if url.user
483 487
      start(url.hostname, url.port,
......
992 996

  
993 997
    public
994 998

  
995
    # Gets data from +path+ on the connected-to host.
999
    # Retrieves data from +path+ on the connected-to host which may be an
1000
    # absolute path String or a URI to extract the path from.
1001
    #
996 1002
    # +initheader+ must be a Hash like { 'Accept' => '*/*', ... },
997 1003
    # and it defaults to an empty hash.
998 1004
    # If +initheader+ doesn't have the key 'accept-encoding', then
......
1336 1342
          begin
1337 1343
            res = HTTPResponse.read_new(@socket)
1338 1344
          end while res.kind_of?(HTTPContinue)
1345

  
1346
          res.uri = req.uri
1347

  
1339 1348
          res.reading_body(@socket, req.response_body_permitted?) {
1340 1349
            yield res if block_given?
1341 1350
          }
......
1377 1386
      if not req.response_body_permitted? and @close_on_empty_response
1378 1387
        req['connection'] ||= 'close'
1379 1388
      end
1389

  
1390
      host = req['host'] || address
1391
      req.update_uri host, port, use_ssl?
1392

  
1380 1393
      req['host'] ||= addr_port()
1381 1394
    end
1382 1395

  
test/net/http/test_httpresponse.rb (working copy)
32 32
    assert_equal('XXX YYY', res.header['x-bar'])
33 33
  end
34 34

  
35
  def test_uri_equals
36
    uri = URI 'http://example'
37

  
38
    response = Net::HTTPResponse.new '1.1', 200, 'OK'
39

  
40
    response.uri = nil
41

  
42
    assert_nil response.uri
43

  
44
    response.uri = uri
45

  
46
    assert_equal uri, response.uri
47
    refute_same  uri, response.uri
48
  end
49

  
35 50
private
36 51

  
37 52
  def dummy_io(str)
test/net/http/test_http.rb (working copy)
224 224
      _test_request__HEAD http
225 225
      _test_request__POST http
226 226
      _test_request__stream_body http
227
      _test_request__uri http
228
      _test_request__uri_host http
227 229
    }
228 230
  end
229 231

  
......
303 305
    assert_equal data, res.body
304 306
  end
305 307

  
308
  def _test_request__uri(http)
309
    uri = URI 'https://example/'
310
    req = Net::HTTP::Get.new(uri)
311

  
312
    res = http.request(req)
313

  
314
    assert_kind_of URI::Generic, req.uri
315

  
316
    refute_equal uri, req.uri
317

  
318
    assert_equal req.uri, res.uri
319

  
320
    refute_same uri,     req.uri
321
    refute_same req.uri, res.uri
322
  end
323

  
324
  def _test_request__uri_host(http)
325
    uri = URI 'http://example/'
326

  
327
    req = Net::HTTP::Get.new(uri)
328
    req['host'] = 'other.example'
329

  
330
    res = http.request(req)
331

  
332
    assert_kind_of URI::Generic, req.uri
333

  
334
    assert_equal URI("http://other.example:#{http.port}"), res.uri
335
  end
336

  
306 337
  def test_send_request
307 338
    start {|http|
308 339
      _test_send_request__GET http
......
616 647
    }
617 648
  end
618 649
end
650

  
test/net/http/test_http_generic_request.rb (revision 0)
1
require 'net/http'
2
require 'test/unit'
3
require 'stringio'
4

  
5
class HTTPGenericResponseTest < Test::Unit::TestCase
6

  
7
  def setup
8
    super
9

  
10
    @GR = Net::HTTPGenericRequest
11

  
12
    @request = @GR.new 'POST', true, true, '/'
13
  end
14

  
15
  def test_initialize
16
    request = @GR.new 'GET', false, true, '/index', 'X-Header' => 'value'
17

  
18
    assert_equal 'GET',    request.method
19
    assert_equal '/index', request.path
20
    assert_nil             request.uri
21

  
22
    assert request.response_body_permitted?
23
    refute request.request_body_permitted?
24

  
25
    assert_equal 'value', request['X-Header']
26
    assert_nil            request['Host']
27
  end
28

  
29
  def test_initialize_uri
30
    uri = URI 'http://example/index?hello=world'
31
    request = @GR.new 'GET', false, true, uri, 'X-Header' => 'value'
32

  
33
    assert_equal 'GET',                request.method
34
    assert_equal '/index?hello=world', request.path
35
    assert_equal uri,                  request.uri
36
    refute_same  uri,                  request.uri
37

  
38
    assert request.response_body_permitted?
39
    refute request.request_body_permitted?
40

  
41
    assert_equal 'value', request['X-Header']
42

  
43
    assert_equal 'example', request['Host']
44
  end
45

  
46
  def test_initialize_uri_host
47
    uri = URI 'http://example/'
48
    request = @GR.new 'GET', false, true, uri, 'Host' => 'other.example'
49

  
50
    assert_equal 'other.example', request['Host']
51
  end
52

  
53
  def test_initialize_uri_nonstandard_port
54
    uri = URI 'http://example:81'
55
    request = @GR.new 'GET', false, true, uri
56

  
57
    assert_equal 'example:81', request['Host']
58
  end
59

  
60
  def test_body_equals
61
    @request.body = 'hello'
62

  
63
    assert_equal 'hello', @request.body
64
  end
65

  
66
  def test_body_stream_equals
67
    @request.body_stream = StringIO.new 'hello'
68

  
69
    assert_equal 'hello', @request.body_stream.read
70
  end
71

  
72
  def test_set_body_internal
73
    @request.set_body_internal 'hello'
74

  
75
    assert_equal 'hello', @request.body
76
  end
77

  
78
  def test_set_body_internal_already_set
79
    @request.body = 'hello'
80

  
81
    assert_raises ArgumentError do
82
      @request.set_body_internal 'other'
83
    end
84

  
85
    @request.body = nil
86
    @request.body_stream = StringIO.new 'hello'
87

  
88
    assert_raises ArgumentError do
89
      @request.set_body_internal 'other'
90
    end
91
  end
92

  
93
  def test_send_request_with_body
94
    socket = StringIO.new
95
    def socket.continue_timeout() end
96

  
97
    @request.send :send_request_with_body, socket, '1.1', '/', 'hello'
98

  
99
    expected = <<-EXPECTED.chomp
100
POST / HTTP/1.1\r
101
Accept: */*\r
102
User-Agent: Ruby\r
103
Content-Length: 5\r
104
Content-Type: application/x-www-form-urlencoded\r
105
\r
106
hello
107
    EXPECTED
108

  
109
    assert_equal expected, socket.string
110
  end
111

  
112
  def test_send_request_with_body_stream
113
    stream = StringIO.new 'hello'
114
    @request['transfer-encoding'] = 'chunked'
115

  
116
    socket = StringIO.new
117
    def socket.continue_timeout() end
118

  
119
    @request.send :send_request_with_body_stream, socket, '1.1', '/', stream
120

  
121
    expected = <<-EXPECTED
122
POST / HTTP/1.1\r
123
Accept: */*\r
124
User-Agent: Ruby\r
125
Transfer-Encoding: chunked\r
126
Content-Type: application/x-www-form-urlencoded\r
127
\r
128
5\r
129
hello\r
130
0\r
131
\r
132
    EXPECTED
133

  
134
    assert_equal expected, socket.string
135
  end
136

  
137
  def test_send_request_with_body_data_multipart
138
    params = [%w[hello world]]
139
    socket = StringIO.new
140
    def socket.continue_timeout() end
141

  
142
    @request.set_form params, 'multipart/form-data'
143

  
144
    @request.send :send_request_with_body_data, socket, '1.1', '/', params
145

  
146
    sent = socket.string
147

  
148
    sent =~ /^Content-Type: multipart\/form-data; boundary=(.*?)\r\n/
149

  
150
    boundary = $1
151

  
152
    sent = sent.gsub(/#{Regexp.escape boundary}/, '<boundary>')
153

  
154
    expected = <<-EXPECTED
155
POST / HTTP/1.1\r
156
Accept: */*\r
157
User-Agent: Ruby\r
158
Content-Type: multipart/form-data; boundary=<boundary>\r
159
Content-Length: 173\r
160
\r
161
--<boundary>\r
162
Content-Disposition: form-data; name="hello"\r
163
\r
164
world\r
165
--<boundary>--\r
166
    EXPECTED
167

  
168
    assert_equal expected, sent
169
  end
170

  
171
  def test_send_request_with_body_data_urlencoded
172
    params = %w[hello world]
173
    socket = StringIO.new
174
    def socket.continue_timeout() end
175

  
176
    @request.send :send_request_with_body_data, socket, '1.1', '/', params
177

  
178
    expected = <<-EXPECTED.chomp
179
POST / HTTP/1.1\r
180
Accept: */*\r
181
User-Agent: Ruby\r
182
Content-Type: application/x-www-form-urlencoded\r
183
Content-Length: 11\r
184
\r
185
hello&world
186
    EXPECTED
187

  
188
    assert_equal expected, socket.string
189
  end
190

  
191
  def test_update_uri
192
    uri = URI 'http://example/index'
193
    request = @GR.new 'GET', false, true, uri, 'X-Header' => 'value'
194

  
195
    request.update_uri 'other.example', 443, true
196

  
197
    assert_equal URI('https://other.example:443/index'), request.uri
198
  end
199

  
200
  def test_update_uri_path
201
    @request.update_uri 'other.example', 80, false
202

  
203
    assert_nil @request.uri
204
  end
205

  
206
end
207