net-http 0.1.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/net/http.rb CHANGED
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # = net/http.rb
4
4
  #
@@ -22,6 +22,7 @@
22
22
 
23
23
  require 'net/protocol'
24
24
  require 'uri'
25
+ require 'resolv'
25
26
  autoload :OpenSSL, 'openssl'
26
27
 
27
28
  module Net #:nodoc:
@@ -31,387 +32,717 @@ module Net #:nodoc:
31
32
  class HTTPHeaderSyntaxError < StandardError; end
32
33
  # :startdoc:
33
34
 
34
- # == An HTTP client API for Ruby.
35
+ # \Class \Net::HTTP provides a rich library that implements the client
36
+ # in a client-server model that uses the \HTTP request-response protocol.
37
+ # For information about \HTTP, see:
38
+ #
39
+ # - {Hypertext Transfer Protocol}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol].
40
+ # - {Technical overview}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Technical_overview].
41
+ #
42
+ # == About the Examples
43
+ #
44
+ # :include: doc/net-http/examples.rdoc
45
+ #
46
+ # == Strategies
47
+ #
48
+ # - If you will make only a few GET requests,
49
+ # consider using {OpenURI}[https://docs.ruby-lang.org/en/master/OpenURI.html].
50
+ # - If you will make only a few requests of all kinds,
51
+ # consider using the various singleton convenience methods in this class.
52
+ # Each of the following methods automatically starts and finishes
53
+ # a {session}[rdoc-ref:Net::HTTP@Sessions] that sends a single request:
54
+ #
55
+ # # Return string response body.
56
+ # Net::HTTP.get(hostname, path)
57
+ # Net::HTTP.get(uri)
58
+ #
59
+ # # Write string response body to $stdout.
60
+ # Net::HTTP.get_print(hostname, path)
61
+ # Net::HTTP.get_print(uri)
62
+ #
63
+ # # Return response as Net::HTTPResponse object.
64
+ # Net::HTTP.get_response(hostname, path)
65
+ # Net::HTTP.get_response(uri)
66
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
67
+ # Net::HTTP.post(uri, data)
68
+ # params = {title: 'foo', body: 'bar', userId: 1}
69
+ # Net::HTTP.post_form(uri, params)
70
+ #
71
+ # - If performance is important, consider using sessions, which lower request overhead.
72
+ # This {session}[rdoc-ref:Net::HTTP@Sessions] has multiple requests for
73
+ # {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods]
74
+ # and {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]:
75
+ #
76
+ # Net::HTTP.start(hostname) do |http|
77
+ # # Session started automatically before block execution.
78
+ # http.get(path)
79
+ # http.head(path)
80
+ # body = 'Some text'
81
+ # http.post(path, body) # Can also have a block.
82
+ # http.put(path, body)
83
+ # http.delete(path)
84
+ # http.options(path)
85
+ # http.trace(path)
86
+ # http.patch(path, body) # Can also have a block.
87
+ # http.copy(path)
88
+ # http.lock(path, body)
89
+ # http.mkcol(path, body)
90
+ # http.move(path)
91
+ # http.propfind(path, body)
92
+ # http.proppatch(path, body)
93
+ # http.unlock(path, body)
94
+ # # Session finished automatically at block exit.
95
+ # end
35
96
  #
36
- # Net::HTTP provides a rich library which can be used to build HTTP
37
- # user-agents. For more details about HTTP see
38
- # [RFC2616](http://www.ietf.org/rfc/rfc2616.txt).
97
+ # The methods cited above are convenience methods that, via their few arguments,
98
+ # allow minimal control over the requests.
99
+ # For greater control, consider using {request objects}[rdoc-ref:Net::HTTPRequest].
39
100
  #
40
- # Net::HTTP is designed to work closely with URI. URI::HTTP#host,
41
- # URI::HTTP#port and URI::HTTP#request_uri are designed to work with
42
- # Net::HTTP.
101
+ # == URIs
43
102
  #
44
- # If you are only performing a few GET requests you should try OpenURI.
103
+ # On the internet, a URI
104
+ # ({Universal Resource Identifier}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier])
105
+ # is a string that identifies a particular resource.
106
+ # It consists of some or all of: scheme, hostname, path, query, and fragment;
107
+ # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax].
45
108
  #
46
- # == Simple Examples
109
+ # A Ruby {URI::Generic}[https://docs.ruby-lang.org/en/master/URI/Generic.html] object
110
+ # represents an internet URI.
111
+ # It provides, among others, methods
112
+ # +scheme+, +hostname+, +path+, +query+, and +fragment+.
47
113
  #
48
- # All examples assume you have loaded Net::HTTP with:
114
+ # === Schemes
49
115
  #
50
- # require 'net/http'
116
+ # An internet \URI has
117
+ # a {scheme}[https://en.wikipedia.org/wiki/List_of_URI_schemes].
51
118
  #
52
- # This will also require 'uri' so you don't need to require it separately.
119
+ # The two schemes supported in \Net::HTTP are <tt>'https'</tt> and <tt>'http'</tt>:
53
120
  #
54
- # The Net::HTTP methods in the following section do not persist
55
- # connections. They are not recommended if you are performing many HTTP
56
- # requests.
121
+ # uri.scheme # => "https"
122
+ # URI('http://example.com').scheme # => "http"
57
123
  #
58
- # === GET
124
+ # === Hostnames
59
125
  #
60
- # Net::HTTP.get('example.com', '/index.html') # => String
126
+ # A hostname identifies a server (host) to which requests may be sent:
61
127
  #
62
- # === GET by URI
128
+ # hostname = uri.hostname # => "jsonplaceholder.typicode.com"
129
+ # Net::HTTP.start(hostname) do |http|
130
+ # # Some HTTP stuff.
131
+ # end
63
132
  #
64
- # uri = URI('http://example.com/index.html?count=10')
65
- # Net::HTTP.get(uri) # => String
133
+ # === Paths
66
134
  #
67
- # === GET with Dynamic Parameters
135
+ # A host-specific path identifies a resource on the host:
68
136
  #
69
- # uri = URI('http://example.com/index.html')
70
- # params = { :limit => 10, :page => 3 }
71
- # uri.query = URI.encode_www_form(params)
137
+ # _uri = uri.dup
138
+ # _uri.path = '/todos/1'
139
+ # hostname = _uri.hostname
140
+ # path = _uri.path
141
+ # Net::HTTP.get(hostname, path)
72
142
  #
73
- # res = Net::HTTP.get_response(uri)
74
- # puts res.body if res.is_a?(Net::HTTPSuccess)
143
+ # === Queries
75
144
  #
76
- # === POST
145
+ # A host-specific query adds name/value pairs to the URI:
77
146
  #
78
- # uri = URI('http://www.example.com/search.cgi')
79
- # res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
80
- # puts res.body
147
+ # _uri = uri.dup
148
+ # params = {userId: 1, completed: false}
149
+ # _uri.query = URI.encode_www_form(params)
150
+ # _uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com?userId=1&completed=false>
151
+ # Net::HTTP.get(_uri)
81
152
  #
82
- # === POST with Multiple Values
153
+ # === Fragments
83
154
  #
84
- # uri = URI('http://www.example.com/search.cgi')
85
- # res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
86
- # puts res.body
155
+ # A {URI fragment}[https://en.wikipedia.org/wiki/URI_fragment] has no effect
156
+ # in \Net::HTTP;
157
+ # the same data is returned, regardless of whether a fragment is included.
87
158
  #
88
- # == How to use Net::HTTP
159
+ # == Request Headers
89
160
  #
90
- # The following example code can be used as the basis of an HTTP user-agent
91
- # which can perform a variety of request types using persistent
92
- # connections.
161
+ # Request headers may be used to pass additional information to the host,
162
+ # similar to arguments passed in a method call;
163
+ # each header is a name/value pair.
93
164
  #
94
- # uri = URI('http://example.com/some_path?query=string')
165
+ # Each of the \Net::HTTP methods that sends a request to the host
166
+ # has optional argument +headers+,
167
+ # where the headers are expressed as a hash of field-name/value pairs:
95
168
  #
96
- # Net::HTTP.start(uri.host, uri.port) do |http|
97
- # request = Net::HTTP::Get.new uri
169
+ # headers = {Accept: 'application/json', Connection: 'Keep-Alive'}
170
+ # Net::HTTP.get(uri, headers)
98
171
  #
99
- # response = http.request request # Net::HTTPResponse object
100
- # end
172
+ # See lists of both standard request fields and common request fields at
173
+ # {Request Fields}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields].
174
+ # A host may also accept other custom fields.
101
175
  #
102
- # Net::HTTP::start immediately creates a connection to an HTTP server which
103
- # is kept open for the duration of the block. The connection will remain
104
- # open for multiple requests in the block if the server indicates it
105
- # supports persistent connections.
176
+ # == \HTTP Sessions
106
177
  #
107
- # If you wish to re-use a connection across multiple HTTP requests without
108
- # automatically closing it you can use ::new and then call #start and
109
- # #finish manually.
178
+ # A _session_ is a connection between a server (host) and a client that:
110
179
  #
111
- # The request types Net::HTTP supports are listed below in the section "HTTP
112
- # Request Classes".
180
+ # - Is begun by instance method Net::HTTP#start.
181
+ # - May contain any number of requests.
182
+ # - Is ended by instance method Net::HTTP#finish.
113
183
  #
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.
184
+ # See example sessions at {Strategies}[rdoc-ref:Net::HTTP@Strategies].
117
185
  #
118
- # === Response Data
186
+ # === Session Using \Net::HTTP.start
119
187
  #
120
- # uri = URI('http://example.com/index.html')
121
- # res = Net::HTTP.get_response(uri)
188
+ # If you have many requests to make to a single host (and port),
189
+ # consider using singleton method Net::HTTP.start with a block;
190
+ # the method handles the session automatically by:
122
191
  #
123
- # # Headers
124
- # res['Set-Cookie'] # => String
125
- # res.get_fields('set-cookie') # => Array
126
- # res.to_hash['set-cookie'] # => Array
127
- # puts "Headers: #{res.to_hash.inspect}"
192
+ # - Calling #start before block execution.
193
+ # - Executing the block.
194
+ # - Calling #finish after block execution.
128
195
  #
129
- # # Status
130
- # puts res.code # => '200'
131
- # puts res.message # => 'OK'
132
- # puts res.class.name # => 'HTTPOK'
196
+ # In the block, you can use these instance methods,
197
+ # each of which that sends a single request:
133
198
  #
134
- # # Body
135
- # puts res.body if res.response_body_permitted?
199
+ # - {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods]:
136
200
  #
137
- # === Following Redirection
201
+ # - #get, #request_get: GET.
202
+ # - #head, #request_head: HEAD.
203
+ # - #post, #request_post: POST.
204
+ # - #delete: DELETE.
205
+ # - #options: OPTIONS.
206
+ # - #trace: TRACE.
207
+ # - #patch: PATCH.
138
208
  #
139
- # Each Net::HTTPResponse object belongs to a class for its response code.
209
+ # - {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]:
140
210
  #
141
- # For example, all 2XX responses are instances of a Net::HTTPSuccess
142
- # subclass, a 3XX response is an instance of a Net::HTTPRedirection
143
- # subclass and a 200 response is an instance of the Net::HTTPOK class. For
144
- # details of response classes, see the section "HTTP Response Classes"
145
- # below.
211
+ # - #copy: COPY.
212
+ # - #lock: LOCK.
213
+ # - #mkcol: MKCOL.
214
+ # - #move: MOVE.
215
+ # - #propfind: PROPFIND.
216
+ # - #proppatch: PROPPATCH.
217
+ # - #unlock: UNLOCK.
146
218
  #
147
- # Using a case statement you can handle various types of responses properly:
219
+ # === Session Using \Net::HTTP.start and \Net::HTTP.finish
148
220
  #
149
- # def fetch(uri_str, limit = 10)
150
- # # You should choose a better exception.
151
- # raise ArgumentError, 'too many HTTP redirects' if limit == 0
221
+ # You can manage a session manually using methods #start and #finish:
152
222
  #
153
- # response = Net::HTTP.get_response(URI(uri_str))
223
+ # http = Net::HTTP.new(hostname)
224
+ # http.start
225
+ # http.get('/todos/1')
226
+ # http.get('/todos/2')
227
+ # http.delete('/posts/1')
228
+ # http.finish # Needed to free resources.
154
229
  #
155
- # case response
156
- # when Net::HTTPSuccess then
157
- # response
158
- # when Net::HTTPRedirection then
159
- # location = response['location']
160
- # warn "redirected to #{location}"
161
- # fetch(location, limit - 1)
162
- # else
163
- # response.value
164
- # end
165
- # end
230
+ # === Single-Request Session
166
231
  #
167
- # print fetch('http://www.ruby-lang.org')
232
+ # Certain convenience methods automatically handle a session by:
168
233
  #
169
- # === POST
234
+ # - Creating an \HTTP object
235
+ # - Starting a session.
236
+ # - Sending a single request.
237
+ # - Finishing the session.
238
+ # - Destroying the object.
170
239
  #
171
- # A POST can be made using the Net::HTTP::Post request class. This example
172
- # creates a URL encoded POST body:
240
+ # Such methods that send GET requests:
173
241
  #
174
- # uri = URI('http://www.example.com/todo.cgi')
175
- # req = Net::HTTP::Post.new(uri)
176
- # req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')
242
+ # - ::get: Returns the string response body.
243
+ # - ::get_print: Writes the string response body to $stdout.
244
+ # - ::get_response: Returns a Net::HTTPResponse object.
177
245
  #
178
- # res = Net::HTTP.start(uri.hostname, uri.port) do |http|
179
- # http.request(req)
180
- # end
246
+ # Such methods that send POST requests:
181
247
  #
182
- # case res
183
- # when Net::HTTPSuccess, Net::HTTPRedirection
184
- # # OK
185
- # else
186
- # res.value
187
- # end
248
+ # - ::post: Posts data to the host.
249
+ # - ::post_form: Posts form data to the host.
188
250
  #
189
- # To send multipart/form-data use Net::HTTPHeader#set_form:
251
+ # == \HTTP Requests and Responses
190
252
  #
191
- # req = Net::HTTP::Post.new(uri)
192
- # req.set_form([['upload', File.open('foo.bar')]], 'multipart/form-data')
253
+ # Many of the methods above are convenience methods,
254
+ # each of which sends a request and returns a string
255
+ # without directly using \Net::HTTPRequest and \Net::HTTPResponse objects.
193
256
  #
194
- # Other requests that can contain a body such as PUT can be created in the
195
- # same way using the corresponding request class (Net::HTTP::Put).
257
+ # You can, however, directly create a request object, send the request,
258
+ # and retrieve the response object; see:
196
259
  #
197
- # === Setting Headers
260
+ # - Net::HTTPRequest.
261
+ # - Net::HTTPResponse.
198
262
  #
199
- # The following example performs a conditional GET using the
200
- # If-Modified-Since header. If the files has not been modified since the
201
- # time in the header a Not Modified response will be returned. See RFC 2616
202
- # section 9.3 for further details.
263
+ # == Following Redirection
203
264
  #
204
- # uri = URI('http://example.com/cached_response')
205
- # file = File.stat 'cached_response'
265
+ # Each returned response is an instance of a subclass of Net::HTTPResponse.
266
+ # See the {response class hierarchy}[rdoc-ref:Net::HTTPResponse@Response+Subclasses].
206
267
  #
207
- # req = Net::HTTP::Get.new(uri)
208
- # req['If-Modified-Since'] = file.mtime.rfc2822
268
+ # In particular, class Net::HTTPRedirection is the parent
269
+ # of all redirection classes.
270
+ # This allows you to craft a case statement to handle redirections properly:
209
271
  #
210
- # res = Net::HTTP.start(uri.hostname, uri.port) {|http|
211
- # http.request(req)
212
- # }
272
+ # def fetch(uri, limit = 10)
273
+ # # You should choose a better exception.
274
+ # raise ArgumentError, 'Too many HTTP redirects' if limit == 0
275
+ #
276
+ # res = Net::HTTP.get_response(URI(uri))
277
+ # case res
278
+ # when Net::HTTPSuccess # Any success class.
279
+ # res
280
+ # when Net::HTTPRedirection # Any redirection class.
281
+ # location = res['Location']
282
+ # warn "Redirected to #{location}"
283
+ # fetch(location, limit - 1)
284
+ # else # Any other class.
285
+ # res.value
286
+ # end
287
+ # end
213
288
  #
214
- # open 'cached_response', 'w' do |io|
215
- # io.write res.body
216
- # end if res.is_a?(Net::HTTPSuccess)
289
+ # fetch(uri)
217
290
  #
218
- # === Basic Authentication
291
+ # == Basic Authentication
219
292
  #
220
293
  # Basic authentication is performed according to
221
- # [RFC2617](http://www.ietf.org/rfc/rfc2617.txt).
222
- #
223
- # uri = URI('http://example.com/index.html?key=value')
294
+ # {RFC2617}[http://www.ietf.org/rfc/rfc2617.txt]:
224
295
  #
225
296
  # req = Net::HTTP::Get.new(uri)
226
- # req.basic_auth 'user', 'pass'
227
- #
228
- # res = Net::HTTP.start(uri.hostname, uri.port) {|http|
297
+ # req.basic_auth('user', 'pass')
298
+ # res = Net::HTTP.start(hostname) do |http|
229
299
  # http.request(req)
230
- # }
231
- # puts res.body
300
+ # end
232
301
  #
233
- # === Streaming Response Bodies
302
+ # == Streaming Response Bodies
234
303
  #
235
- # By default Net::HTTP reads an entire response into memory. If you are
304
+ # By default \Net::HTTP reads an entire response into memory. If you are
236
305
  # handling large files or wish to implement a progress bar you can instead
237
306
  # stream the body directly to an IO.
238
307
  #
239
- # uri = URI('http://example.com/large_file')
240
- #
241
- # Net::HTTP.start(uri.host, uri.port) do |http|
242
- # request = Net::HTTP::Get.new uri
243
- #
244
- # http.request request do |response|
245
- # open 'large_file', 'w' do |io|
246
- # response.read_body do |chunk|
247
- # io.write chunk
308
+ # Net::HTTP.start(hostname) do |http|
309
+ # req = Net::HTTP::Get.new(uri)
310
+ # http.request(req) do |res|
311
+ # open('t.tmp', 'w') do |f|
312
+ # res.read_body do |chunk|
313
+ # f.write chunk
248
314
  # end
249
315
  # end
250
316
  # end
251
317
  # end
252
318
  #
253
- # === HTTPS
254
- #
255
- # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=.
319
+ # == HTTPS
256
320
  #
257
- # uri = URI('https://secure.example.com/some_path?query=string')
321
+ # HTTPS is enabled for an \HTTP connection by Net::HTTP#use_ssl=:
258
322
  #
259
- # Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
260
- # request = Net::HTTP::Get.new uri
261
- # response = http.request request # Net::HTTPResponse object
323
+ # Net::HTTP.start(hostname, :use_ssl => true) do |http|
324
+ # req = Net::HTTP::Get.new(uri)
325
+ # res = http.request(req)
262
326
  # end
263
327
  #
264
- # Or if you simply want to make a GET request, you may pass in an URI
265
- # object that has an HTTPS URL. Net::HTTP automatically turns on TLS
266
- # verification if the URI object has a 'https' URI scheme.
328
+ # Or if you simply want to make a GET request, you may pass in a URI
329
+ # object that has an \HTTPS URL. \Net::HTTP automatically turns on TLS
330
+ # verification if the URI object has a 'https' URI scheme:
331
+ #
332
+ # uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com/>
333
+ # Net::HTTP.get(uri)
334
+ #
335
+ # == Proxy Server
336
+ #
337
+ # An \HTTP object can have
338
+ # a {proxy server}[https://en.wikipedia.org/wiki/Proxy_server].
339
+ #
340
+ # You can create an \HTTP object with a proxy server
341
+ # using method Net::HTTP.new or method Net::HTTP.start.
342
+ #
343
+ # The proxy may be defined either by argument +p_addr+
344
+ # or by environment variable <tt>'http_proxy'</tt>.
345
+ #
346
+ # === Proxy Using Argument +p_addr+ as a \String
347
+ #
348
+ # When argument +p_addr+ is a string hostname,
349
+ # the returned +http+ has the given host as its proxy:
350
+ #
351
+ # http = Net::HTTP.new(hostname, nil, 'proxy.example')
352
+ # http.proxy? # => true
353
+ # http.proxy_from_env? # => false
354
+ # http.proxy_address # => "proxy.example"
355
+ # # These use default values.
356
+ # http.proxy_port # => 80
357
+ # http.proxy_user # => nil
358
+ # http.proxy_pass # => nil
359
+ #
360
+ # The port, username, and password for the proxy may also be given:
267
361
  #
268
- # uri = URI('https://example.com/')
269
- # Net::HTTP.get(uri) # => String
362
+ # http = Net::HTTP.new(hostname, nil, 'proxy.example', 8000, 'pname', 'ppass')
363
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
364
+ # http.proxy? # => true
365
+ # http.proxy_from_env? # => false
366
+ # http.proxy_address # => "proxy.example"
367
+ # http.proxy_port # => 8000
368
+ # http.proxy_user # => "pname"
369
+ # http.proxy_pass # => "ppass"
270
370
  #
271
- # In previous versions of Ruby you would need to require 'net/https' to use
272
- # HTTPS. This is no longer true.
371
+ # === Proxy Using '<tt>ENV['http_proxy']</tt>'
372
+ #
373
+ # When environment variable <tt>'http_proxy'</tt>
374
+ # is set to a \URI string,
375
+ # the returned +http+ will have the server at that URI as its proxy;
376
+ # note that the \URI string must have a protocol
377
+ # such as <tt>'http'</tt> or <tt>'https'</tt>:
378
+ #
379
+ # ENV['http_proxy'] = 'http://example.com'
380
+ # http = Net::HTTP.new(hostname)
381
+ # http.proxy? # => true
382
+ # http.proxy_from_env? # => true
383
+ # http.proxy_address # => "example.com"
384
+ # # These use default values.
385
+ # http.proxy_port # => 80
386
+ # http.proxy_user # => nil
387
+ # http.proxy_pass # => nil
388
+ #
389
+ # The \URI string may include proxy username, password, and port number:
390
+ #
391
+ # ENV['http_proxy'] = 'http://pname:ppass@example.com:8000'
392
+ # http = Net::HTTP.new(hostname)
393
+ # http.proxy? # => true
394
+ # http.proxy_from_env? # => true
395
+ # http.proxy_address # => "example.com"
396
+ # http.proxy_port # => 8000
397
+ # http.proxy_user # => "pname"
398
+ # http.proxy_pass # => "ppass"
399
+ #
400
+ # === Filtering Proxies
401
+ #
402
+ # With method Net::HTTP.new (but not Net::HTTP.start),
403
+ # you can use argument +p_no_proxy+ to filter proxies:
404
+ #
405
+ # - Reject a certain address:
406
+ #
407
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example')
408
+ # http.proxy_address # => nil
409
+ #
410
+ # - Reject certain domains or subdomains:
411
+ #
412
+ # http = Net::HTTP.new('example.com', nil, 'my.proxy.example', 8000, 'pname', 'ppass', 'proxy.example')
413
+ # http.proxy_address # => nil
414
+ #
415
+ # - Reject certain addresses and port combinations:
416
+ #
417
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:1234')
418
+ # http.proxy_address # => "proxy.example"
419
+ #
420
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:8000')
421
+ # http.proxy_address # => nil
422
+ #
423
+ # - Reject a list of the types above delimited using a comma:
424
+ #
425
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000')
426
+ # http.proxy_address # => nil
427
+ #
428
+ # http = Net::HTTP.new('example.com', nil, 'my.proxy', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000')
429
+ # http.proxy_address # => nil
430
+ #
431
+ # == Compression and Decompression
432
+ #
433
+ # \Net::HTTP does not compress the body of a request before sending.
434
+ #
435
+ # By default, \Net::HTTP adds header <tt>'Accept-Encoding'</tt>
436
+ # to a new {request object}[rdoc-ref:Net::HTTPRequest]:
437
+ #
438
+ # Net::HTTP::Get.new(uri)['Accept-Encoding']
439
+ # # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
440
+ #
441
+ # This requests the server to zip-encode the response body if there is one;
442
+ # the server is not required to do so.
443
+ #
444
+ # \Net::HTTP does not automatically decompress a response body
445
+ # if the response has header <tt>'Content-Range'</tt>.
446
+ #
447
+ # Otherwise decompression (or not) depends on the value of header
448
+ # {Content-Encoding}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-encoding-response-header]:
449
+ #
450
+ # - <tt>'deflate'</tt>, <tt>'gzip'</tt>, or <tt>'x-gzip'</tt>:
451
+ # decompresses the body and deletes the header.
452
+ # - <tt>'none'</tt> or <tt>'identity'</tt>:
453
+ # does not decompress the body, but deletes the header.
454
+ # - Any other value:
455
+ # leaves the body and header unchanged.
456
+ #
457
+ # == What's Here
458
+ #
459
+ # This is a categorized summary of methods and attributes.
460
+ #
461
+ # === \Net::HTTP Objects
462
+ #
463
+ # - {::new}[rdoc-ref:Net::HTTP.new]:
464
+ # Creates a new instance.
465
+ # - {#inspect}[rdoc-ref:Net::HTTP#inspect]:
466
+ # Returns a string representation of +self+.
467
+ #
468
+ # === Sessions
469
+ #
470
+ # - {::start}[rdoc-ref:Net::HTTP.start]:
471
+ # Begins a new session in a new \Net::HTTP object.
472
+ # - {#started?}[rdoc-ref:Net::HTTP#started?]
473
+ # (aliased as {#active?}[rdoc-ref:Net::HTTP#active?]):
474
+ # Returns whether in a session.
475
+ # - {#finish}[rdoc-ref:Net::HTTP#finish]:
476
+ # Ends an active session.
477
+ # - {#start}[rdoc-ref:Net::HTTP#start]:
478
+ # Begins a new session in an existing \Net::HTTP object (+self+).
479
+ #
480
+ # === Connections
481
+ #
482
+ # - {:continue_timeout}[rdoc-ref:Net::HTTP#continue_timeout]:
483
+ # Returns the continue timeout.
484
+ # - {#continue_timeout=}[rdoc-ref:Net::HTTP#continue_timeout=]:
485
+ # Sets the continue timeout seconds.
486
+ # - {:keep_alive_timeout}[rdoc-ref:Net::HTTP#keep_alive_timeout]:
487
+ # Returns the keep-alive timeout.
488
+ # - {:keep_alive_timeout=}[rdoc-ref:Net::HTTP#keep_alive_timeout=]:
489
+ # Sets the keep-alive timeout.
490
+ # - {:max_retries}[rdoc-ref:Net::HTTP#max_retries]:
491
+ # Returns the maximum retries.
492
+ # - {#max_retries=}[rdoc-ref:Net::HTTP#max_retries=]:
493
+ # Sets the maximum retries.
494
+ # - {:open_timeout}[rdoc-ref:Net::HTTP#open_timeout]:
495
+ # Returns the open timeout.
496
+ # - {:open_timeout=}[rdoc-ref:Net::HTTP#open_timeout=]:
497
+ # Sets the open timeout.
498
+ # - {:read_timeout}[rdoc-ref:Net::HTTP#read_timeout]:
499
+ # Returns the open timeout.
500
+ # - {:read_timeout=}[rdoc-ref:Net::HTTP#read_timeout=]:
501
+ # Sets the read timeout.
502
+ # - {:ssl_timeout}[rdoc-ref:Net::HTTP#ssl_timeout]:
503
+ # Returns the ssl timeout.
504
+ # - {:ssl_timeout=}[rdoc-ref:Net::HTTP#ssl_timeout=]:
505
+ # Sets the ssl timeout.
506
+ # - {:write_timeout}[rdoc-ref:Net::HTTP#write_timeout]:
507
+ # Returns the write timeout.
508
+ # - {write_timeout=}[rdoc-ref:Net::HTTP#write_timeout=]:
509
+ # Sets the write timeout.
510
+ #
511
+ # === Requests
512
+ #
513
+ # - {::get}[rdoc-ref:Net::HTTP.get]:
514
+ # Sends a GET request and returns the string response body.
515
+ # - {::get_print}[rdoc-ref:Net::HTTP.get_print]:
516
+ # Sends a GET request and write the string response body to $stdout.
517
+ # - {::get_response}[rdoc-ref:Net::HTTP.get_response]:
518
+ # Sends a GET request and returns a response object.
519
+ # - {::post_form}[rdoc-ref:Net::HTTP.post_form]:
520
+ # Sends a POST request with form data and returns a response object.
521
+ # - {::post}[rdoc-ref:Net::HTTP.post]:
522
+ # Sends a POST request with data and returns a response object.
523
+ # - {#copy}[rdoc-ref:Net::HTTP#copy]:
524
+ # Sends a COPY request and returns a response object.
525
+ # - {#delete}[rdoc-ref:Net::HTTP#delete]:
526
+ # Sends a DELETE request and returns a response object.
527
+ # - {#get}[rdoc-ref:Net::HTTP#get]:
528
+ # Sends a GET request and returns a response object.
529
+ # - {#head}[rdoc-ref:Net::HTTP#head]:
530
+ # Sends a HEAD request and returns a response object.
531
+ # - {#lock}[rdoc-ref:Net::HTTP#lock]:
532
+ # Sends a LOCK request and returns a response object.
533
+ # - {#mkcol}[rdoc-ref:Net::HTTP#mkcol]:
534
+ # Sends a MKCOL request and returns a response object.
535
+ # - {#move}[rdoc-ref:Net::HTTP#move]:
536
+ # Sends a MOVE request and returns a response object.
537
+ # - {#options}[rdoc-ref:Net::HTTP#options]:
538
+ # Sends a OPTIONS request and returns a response object.
539
+ # - {#patch}[rdoc-ref:Net::HTTP#patch]:
540
+ # Sends a PATCH request and returns a response object.
541
+ # - {#post}[rdoc-ref:Net::HTTP#post]:
542
+ # Sends a POST request and returns a response object.
543
+ # - {#propfind}[rdoc-ref:Net::HTTP#propfind]:
544
+ # Sends a PROPFIND request and returns a response object.
545
+ # - {#proppatch}[rdoc-ref:Net::HTTP#proppatch]:
546
+ # Sends a PROPPATCH request and returns a response object.
547
+ # - {#put}[rdoc-ref:Net::HTTP#put]:
548
+ # Sends a PUT request and returns a response object.
549
+ # - {#request}[rdoc-ref:Net::HTTP#request]:
550
+ # Sends a request and returns a response object.
551
+ # - {#request_get}[rdoc-ref:Net::HTTP#request_get]
552
+ # (aliased as {#get2}[rdoc-ref:Net::HTTP#get2]):
553
+ # Sends a GET request and forms a response object;
554
+ # if a block given, calls the block with the object,
555
+ # otherwise returns the object.
556
+ # - {#request_head}[rdoc-ref:Net::HTTP#request_head]
557
+ # (aliased as {#head2}[rdoc-ref:Net::HTTP#head2]):
558
+ # Sends a HEAD request and forms a response object;
559
+ # if a block given, calls the block with the object,
560
+ # otherwise returns the object.
561
+ # - {#request_post}[rdoc-ref:Net::HTTP#request_post]
562
+ # (aliased as {#post2}[rdoc-ref:Net::HTTP#post2]):
563
+ # Sends a POST request and forms a response object;
564
+ # if a block given, calls the block with the object,
565
+ # otherwise returns the object.
566
+ # - {#send_request}[rdoc-ref:Net::HTTP#send_request]:
567
+ # Sends a request and returns a response object.
568
+ # - {#trace}[rdoc-ref:Net::HTTP#trace]:
569
+ # Sends a TRACE request and returns a response object.
570
+ # - {#unlock}[rdoc-ref:Net::HTTP#unlock]:
571
+ # Sends an UNLOCK request and returns a response object.
572
+ #
573
+ # === Responses
574
+ #
575
+ # - {:close_on_empty_response}[rdoc-ref:Net::HTTP#close_on_empty_response]:
576
+ # Returns whether to close connection on empty response.
577
+ # - {:close_on_empty_response=}[rdoc-ref:Net::HTTP#close_on_empty_response=]:
578
+ # Sets whether to close connection on empty response.
579
+ # - {:ignore_eof}[rdoc-ref:Net::HTTP#ignore_eof]:
580
+ # Returns whether to ignore end-of-file when reading a response body
581
+ # with <tt>Content-Length</tt> headers.
582
+ # - {:ignore_eof=}[rdoc-ref:Net::HTTP#ignore_eof=]:
583
+ # Sets whether to ignore end-of-file when reading a response body
584
+ # with <tt>Content-Length</tt> headers.
585
+ # - {:response_body_encoding}[rdoc-ref:Net::HTTP#response_body_encoding]:
586
+ # Returns the encoding to use for the response body.
587
+ # - {#response_body_encoding=}[rdoc-ref:Net::HTTP#response_body_encoding=]:
588
+ # Sets the response body encoding.
273
589
  #
274
590
  # === Proxies
275
591
  #
276
- # Net::HTTP will automatically create a proxy from the +http_proxy+
277
- # environment variable if it is present. To disable use of +http_proxy+,
278
- # pass +nil+ for the proxy address.
279
- #
280
- # You may also create a custom proxy:
281
- #
282
- # proxy_addr = 'your.proxy.host'
283
- # proxy_port = 8080
284
- #
285
- # Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http|
286
- # # always proxy via your.proxy.addr:8080
287
- # }
288
- #
289
- # See Net::HTTP.new for further details and examples such as proxies that
290
- # require a username and password.
291
- #
292
- # === Compression
293
- #
294
- # Net::HTTP automatically adds Accept-Encoding for compression of response
295
- # bodies and automatically decompresses gzip and deflate responses unless a
296
- # Range header was sent.
297
- #
298
- # Compression can be disabled through the Accept-Encoding: identity header.
299
- #
300
- # == HTTP Request Classes
301
- #
302
- # Here is the HTTP request class hierarchy.
303
- #
304
- # * Net::HTTPRequest
305
- # * Net::HTTP::Get
306
- # * Net::HTTP::Head
307
- # * Net::HTTP::Post
308
- # * Net::HTTP::Patch
309
- # * Net::HTTP::Put
310
- # * Net::HTTP::Proppatch
311
- # * Net::HTTP::Lock
312
- # * Net::HTTP::Unlock
313
- # * Net::HTTP::Options
314
- # * Net::HTTP::Propfind
315
- # * Net::HTTP::Delete
316
- # * Net::HTTP::Move
317
- # * Net::HTTP::Copy
318
- # * Net::HTTP::Mkcol
319
- # * Net::HTTP::Trace
320
- #
321
- # == HTTP Response Classes
322
- #
323
- # Here is HTTP response class hierarchy. All classes are defined in Net
324
- # module and are subclasses of Net::HTTPResponse.
325
- #
326
- # HTTPUnknownResponse:: For unhandled HTTP extensions
327
- # HTTPInformation:: 1xx
328
- # HTTPContinue:: 100
329
- # HTTPSwitchProtocol:: 101
330
- # HTTPSuccess:: 2xx
331
- # HTTPOK:: 200
332
- # HTTPCreated:: 201
333
- # HTTPAccepted:: 202
334
- # HTTPNonAuthoritativeInformation:: 203
335
- # HTTPNoContent:: 204
336
- # HTTPResetContent:: 205
337
- # HTTPPartialContent:: 206
338
- # HTTPMultiStatus:: 207
339
- # HTTPIMUsed:: 226
340
- # HTTPRedirection:: 3xx
341
- # HTTPMultipleChoices:: 300
342
- # HTTPMovedPermanently:: 301
343
- # HTTPFound:: 302
344
- # HTTPSeeOther:: 303
345
- # HTTPNotModified:: 304
346
- # HTTPUseProxy:: 305
347
- # HTTPTemporaryRedirect:: 307
348
- # HTTPClientError:: 4xx
349
- # HTTPBadRequest:: 400
350
- # HTTPUnauthorized:: 401
351
- # HTTPPaymentRequired:: 402
352
- # HTTPForbidden:: 403
353
- # HTTPNotFound:: 404
354
- # HTTPMethodNotAllowed:: 405
355
- # HTTPNotAcceptable:: 406
356
- # HTTPProxyAuthenticationRequired:: 407
357
- # HTTPRequestTimeOut:: 408
358
- # HTTPConflict:: 409
359
- # HTTPGone:: 410
360
- # HTTPLengthRequired:: 411
361
- # HTTPPreconditionFailed:: 412
362
- # HTTPRequestEntityTooLarge:: 413
363
- # HTTPRequestURITooLong:: 414
364
- # HTTPUnsupportedMediaType:: 415
365
- # HTTPRequestedRangeNotSatisfiable:: 416
366
- # HTTPExpectationFailed:: 417
367
- # HTTPUnprocessableEntity:: 422
368
- # HTTPLocked:: 423
369
- # HTTPFailedDependency:: 424
370
- # HTTPUpgradeRequired:: 426
371
- # HTTPPreconditionRequired:: 428
372
- # HTTPTooManyRequests:: 429
373
- # HTTPRequestHeaderFieldsTooLarge:: 431
374
- # HTTPUnavailableForLegalReasons:: 451
375
- # HTTPServerError:: 5xx
376
- # HTTPInternalServerError:: 500
377
- # HTTPNotImplemented:: 501
378
- # HTTPBadGateway:: 502
379
- # HTTPServiceUnavailable:: 503
380
- # HTTPGatewayTimeOut:: 504
381
- # HTTPVersionNotSupported:: 505
382
- # HTTPInsufficientStorage:: 507
383
- # HTTPNetworkAuthenticationRequired:: 511
384
- #
385
- # There is also the Net::HTTPBadResponse exception which is raised when
386
- # there is a protocol error.
592
+ # - {:proxy_address}[rdoc-ref:Net::HTTP#proxy_address]:
593
+ # Returns the proxy address.
594
+ # - {:proxy_address=}[rdoc-ref:Net::HTTP#proxy_address=]:
595
+ # Sets the proxy address.
596
+ # - {::proxy_class?}[rdoc-ref:Net::HTTP.proxy_class?]:
597
+ # Returns whether +self+ is a proxy class.
598
+ # - {#proxy?}[rdoc-ref:Net::HTTP#proxy?]:
599
+ # Returns whether +self+ has a proxy.
600
+ # - {#proxy_address}[rdoc-ref:Net::HTTP#proxy_address]
601
+ # (aliased as {#proxyaddr}[rdoc-ref:Net::HTTP#proxyaddr]):
602
+ # Returns the proxy address.
603
+ # - {#proxy_from_env?}[rdoc-ref:Net::HTTP#proxy_from_env?]:
604
+ # Returns whether the proxy is taken from an environment variable.
605
+ # - {:proxy_from_env=}[rdoc-ref:Net::HTTP#proxy_from_env=]:
606
+ # Sets whether the proxy is to be taken from an environment variable.
607
+ # - {:proxy_pass}[rdoc-ref:Net::HTTP#proxy_pass]:
608
+ # Returns the proxy password.
609
+ # - {:proxy_pass=}[rdoc-ref:Net::HTTP#proxy_pass=]:
610
+ # Sets the proxy password.
611
+ # - {:proxy_port}[rdoc-ref:Net::HTTP#proxy_port]:
612
+ # Returns the proxy port.
613
+ # - {:proxy_port=}[rdoc-ref:Net::HTTP#proxy_port=]:
614
+ # Sets the proxy port.
615
+ # - {#proxy_user}[rdoc-ref:Net::HTTP#proxy_user]:
616
+ # Returns the proxy user name.
617
+ # - {:proxy_user=}[rdoc-ref:Net::HTTP#proxy_user=]:
618
+ # Sets the proxy user.
619
+ #
620
+ # === Security
621
+ #
622
+ # - {:ca_file}[rdoc-ref:Net::HTTP#ca_file]:
623
+ # Returns the path to a CA certification file.
624
+ # - {:ca_file=}[rdoc-ref:Net::HTTP#ca_file=]:
625
+ # Sets the path to a CA certification file.
626
+ # - {:ca_path}[rdoc-ref:Net::HTTP#ca_path]:
627
+ # Returns the path of to CA directory containing certification files.
628
+ # - {:ca_path=}[rdoc-ref:Net::HTTP#ca_path=]:
629
+ # Sets the path of to CA directory containing certification files.
630
+ # - {:cert}[rdoc-ref:Net::HTTP#cert]:
631
+ # Returns the OpenSSL::X509::Certificate object to be used for client certification.
632
+ # - {:cert=}[rdoc-ref:Net::HTTP#cert=]:
633
+ # Sets the OpenSSL::X509::Certificate object to be used for client certification.
634
+ # - {:cert_store}[rdoc-ref:Net::HTTP#cert_store]:
635
+ # Returns the X509::Store to be used for verifying peer certificate.
636
+ # - {:cert_store=}[rdoc-ref:Net::HTTP#cert_store=]:
637
+ # Sets the X509::Store to be used for verifying peer certificate.
638
+ # - {:ciphers}[rdoc-ref:Net::HTTP#ciphers]:
639
+ # Returns the available SSL ciphers.
640
+ # - {:ciphers=}[rdoc-ref:Net::HTTP#ciphers=]:
641
+ # Sets the available SSL ciphers.
642
+ # - {:extra_chain_cert}[rdoc-ref:Net::HTTP#extra_chain_cert]:
643
+ # Returns the extra X509 certificates to be added to the certificate chain.
644
+ # - {:extra_chain_cert=}[rdoc-ref:Net::HTTP#extra_chain_cert=]:
645
+ # Sets the extra X509 certificates to be added to the certificate chain.
646
+ # - {:key}[rdoc-ref:Net::HTTP#key]:
647
+ # Returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
648
+ # - {:key=}[rdoc-ref:Net::HTTP#key=]:
649
+ # Sets the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
650
+ # - {:max_version}[rdoc-ref:Net::HTTP#max_version]:
651
+ # Returns the maximum SSL version.
652
+ # - {:max_version=}[rdoc-ref:Net::HTTP#max_version=]:
653
+ # Sets the maximum SSL version.
654
+ # - {:min_version}[rdoc-ref:Net::HTTP#min_version]:
655
+ # Returns the minimum SSL version.
656
+ # - {:min_version=}[rdoc-ref:Net::HTTP#min_version=]:
657
+ # Sets the minimum SSL version.
658
+ # - {#peer_cert}[rdoc-ref:Net::HTTP#peer_cert]:
659
+ # Returns the X509 certificate chain for the session's socket peer.
660
+ # - {:ssl_version}[rdoc-ref:Net::HTTP#ssl_version]:
661
+ # Returns the SSL version.
662
+ # - {:ssl_version=}[rdoc-ref:Net::HTTP#ssl_version=]:
663
+ # Sets the SSL version.
664
+ # - {#use_ssl=}[rdoc-ref:Net::HTTP#use_ssl=]:
665
+ # Sets whether a new session is to use Transport Layer Security.
666
+ # - {#use_ssl?}[rdoc-ref:Net::HTTP#use_ssl?]:
667
+ # Returns whether +self+ uses SSL.
668
+ # - {:verify_callback}[rdoc-ref:Net::HTTP#verify_callback]:
669
+ # Returns the callback for the server certification verification.
670
+ # - {:verify_callback=}[rdoc-ref:Net::HTTP#verify_callback=]:
671
+ # Sets the callback for the server certification verification.
672
+ # - {:verify_depth}[rdoc-ref:Net::HTTP#verify_depth]:
673
+ # Returns the maximum depth for the certificate chain verification.
674
+ # - {:verify_depth=}[rdoc-ref:Net::HTTP#verify_depth=]:
675
+ # Sets the maximum depth for the certificate chain verification.
676
+ # - {:verify_hostname}[rdoc-ref:Net::HTTP#verify_hostname]:
677
+ # Returns the flags for server the certification verification at the beginning of the SSL/TLS session.
678
+ # - {:verify_hostname=}[rdoc-ref:Net::HTTP#verify_hostname=]:
679
+ # Sets he flags for server the certification verification at the beginning of the SSL/TLS session.
680
+ # - {:verify_mode}[rdoc-ref:Net::HTTP#verify_mode]:
681
+ # Returns the flags for server the certification verification at the beginning of the SSL/TLS session.
682
+ # - {:verify_mode=}[rdoc-ref:Net::HTTP#verify_mode=]:
683
+ # Sets the flags for server the certification verification at the beginning of the SSL/TLS session.
684
+ #
685
+ # === Addresses and Ports
686
+ #
687
+ # - {:address}[rdoc-ref:Net::HTTP#address]:
688
+ # Returns the string host name or host IP.
689
+ # - {::default_port}[rdoc-ref:Net::HTTP.default_port]:
690
+ # Returns integer 80, the default port to use for HTTP requests.
691
+ # - {::http_default_port}[rdoc-ref:Net::HTTP.http_default_port]:
692
+ # Returns integer 80, the default port to use for HTTP requests.
693
+ # - {::https_default_port}[rdoc-ref:Net::HTTP.https_default_port]:
694
+ # Returns integer 443, the default port to use for HTTPS requests.
695
+ # - {#ipaddr}[rdoc-ref:Net::HTTP#ipaddr]:
696
+ # Returns the IP address for the connection.
697
+ # - {#ipaddr=}[rdoc-ref:Net::HTTP#ipaddr=]:
698
+ # Sets the IP address for the connection.
699
+ # - {:local_host}[rdoc-ref:Net::HTTP#local_host]:
700
+ # Returns the string local host used to establish the connection.
701
+ # - {:local_host=}[rdoc-ref:Net::HTTP#local_host=]:
702
+ # Sets the string local host used to establish the connection.
703
+ # - {:local_port}[rdoc-ref:Net::HTTP#local_port]:
704
+ # Returns the integer local port used to establish the connection.
705
+ # - {:local_port=}[rdoc-ref:Net::HTTP#local_port=]:
706
+ # Sets the integer local port used to establish the connection.
707
+ # - {:port}[rdoc-ref:Net::HTTP#port]:
708
+ # Returns the integer port number.
709
+ #
710
+ # === \HTTP Version
711
+ #
712
+ # - {::version_1_2?}[rdoc-ref:Net::HTTP.version_1_2?]
713
+ # (aliased as {::is_version_1_2?}[rdoc-ref:Net::HTTP.is_version_1_2?]
714
+ # and {::version_1_2}[rdoc-ref:Net::HTTP.version_1_2]):
715
+ # Returns true; retained for compatibility.
716
+ #
717
+ # === Debugging
718
+ #
719
+ # - {#set_debug_output}[rdoc-ref:Net::HTTP#set_debug_output]:
720
+ # Sets the output stream for debugging.
387
721
  #
388
722
  class HTTP < Protocol
389
723
 
390
724
  # :stopdoc:
391
- VERSION = "0.1.1"
392
- Revision = %q$Revision$.split[1]
725
+ VERSION = "0.4.1"
393
726
  HTTPVersion = '1.1'
394
727
  begin
395
728
  require 'zlib'
396
- require 'stringio' #for our purposes (unpacking gzip) lump these together
397
729
  HAVE_ZLIB=true
398
730
  rescue LoadError
399
731
  HAVE_ZLIB=false
400
732
  end
401
733
  # :startdoc:
402
734
 
403
- # Turns on net/http 1.2 (Ruby 1.8) features.
404
- # Defaults to ON in Ruby 1.8 or later.
735
+ # Returns +true+; retained for compatibility.
405
736
  def HTTP.version_1_2
406
737
  true
407
738
  end
408
739
 
409
- # Returns true if net/http is in version 1.2 mode.
410
- # Defaults to true.
740
+ # Returns +true+; retained for compatibility.
411
741
  def HTTP.version_1_2?
412
742
  true
413
743
  end
414
744
 
745
+ # Returns +false+; retained for compatibility.
415
746
  def HTTP.version_1_1? #:nodoc:
416
747
  false
417
748
  end
@@ -421,25 +752,12 @@ module Net #:nodoc:
421
752
  alias is_version_1_2? version_1_2? #:nodoc:
422
753
  end
423
754
 
755
+ # :call-seq:
756
+ # Net::HTTP.get_print(hostname, path, port = 80) -> nil
757
+ # Net::HTTP:get_print(uri, headers = {}, port = uri.port) -> nil
424
758
  #
425
- # short cut methods
426
- #
427
-
428
- #
429
- # Gets the body text from the target and outputs it to $stdout. The
430
- # target can either be specified as
431
- # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
432
- #
433
- # Net::HTTP.get_print URI('http://www.example.com/index.html')
434
- #
435
- # or:
436
- #
437
- # Net::HTTP.get_print 'www.example.com', '/index.html'
438
- #
439
- # you can also specify request headers:
440
- #
441
- # Net::HTTP.get_print URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }
442
- #
759
+ # Like Net::HTTP.get, but writes the returned body to $stdout;
760
+ # returns +nil+.
443
761
  def HTTP.get_print(uri_or_host, path_or_headers = nil, port = nil)
444
762
  get_response(uri_or_host, path_or_headers, port) {|res|
445
763
  res.read_body do |chunk|
@@ -449,40 +767,48 @@ module Net #:nodoc:
449
767
  nil
450
768
  end
451
769
 
452
- # Sends a GET request to the target and returns the HTTP response
453
- # as a string. The target can either be specified as
454
- # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
455
- #
456
- # print Net::HTTP.get(URI('http://www.example.com/index.html'))
770
+ # :call-seq:
771
+ # Net::HTTP.get(hostname, path, port = 80) -> body
772
+ # Net::HTTP:get(uri, headers = {}, port = uri.port) -> body
457
773
  #
458
- # or:
774
+ # Sends a GET request and returns the \HTTP response body as a string.
459
775
  #
460
- # print Net::HTTP.get('www.example.com', '/index.html')
776
+ # With string arguments +hostname+ and +path+:
461
777
  #
462
- # you can also specify request headers:
778
+ # hostname = 'jsonplaceholder.typicode.com'
779
+ # path = '/todos/1'
780
+ # puts Net::HTTP.get(hostname, path)
463
781
  #
464
- # Net::HTTP.get(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' })
782
+ # Output:
465
783
  #
466
- def HTTP.get(uri_or_host, path_or_headers = nil, port = nil)
467
- get_response(uri_or_host, path_or_headers, port).body
468
- end
469
-
470
- # Sends a GET request to the target and returns the HTTP response
471
- # as a Net::HTTPResponse object. The target can either be specified as
472
- # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
784
+ # {
785
+ # "userId": 1,
786
+ # "id": 1,
787
+ # "title": "delectus aut autem",
788
+ # "completed": false
789
+ # }
473
790
  #
474
- # res = Net::HTTP.get_response(URI('http://www.example.com/index.html'))
475
- # print res.body
791
+ # With URI object +uri+ and optional hash argument +headers+:
476
792
  #
477
- # or:
793
+ # uri = URI('https://jsonplaceholder.typicode.com/todos/1')
794
+ # headers = {'Content-type' => 'application/json; charset=UTF-8'}
795
+ # Net::HTTP.get(uri, headers)
478
796
  #
479
- # res = Net::HTTP.get_response('www.example.com', '/index.html')
480
- # print res.body
797
+ # Related:
481
798
  #
482
- # you can also specify request headers:
799
+ # - Net::HTTP::Get: request class for \HTTP method +GET+.
800
+ # - Net::HTTP#get: convenience method for \HTTP method +GET+.
483
801
  #
484
- # Net::HTTP.get_response(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' })
802
+ def HTTP.get(uri_or_host, path_or_headers = nil, port = nil)
803
+ get_response(uri_or_host, path_or_headers, port).body
804
+ end
805
+
806
+ # :call-seq:
807
+ # Net::HTTP.get_response(hostname, path, port = 80) -> http_response
808
+ # Net::HTTP:get_response(uri, headers = {}, port = uri.port) -> http_response
485
809
  #
810
+ # Like Net::HTTP.get, but returns a Net::HTTPResponse object
811
+ # instead of the body string.
486
812
  def HTTP.get_response(uri_or_host, path_or_headers = nil, port = nil, &block)
487
813
  if path_or_headers && !path_or_headers.is_a?(Hash)
488
814
  host = uri_or_host
@@ -500,16 +826,31 @@ module Net #:nodoc:
500
826
  end
501
827
  end
502
828
 
503
- # Posts data to the specified URI object.
829
+ # Posts data to a host; returns a Net::HTTPResponse object.
504
830
  #
505
- # Example:
831
+ # Argument +url+ must be a URL;
832
+ # argument +data+ must be a string:
833
+ #
834
+ # _uri = uri.dup
835
+ # _uri.path = '/posts'
836
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
837
+ # headers = {'content-type': 'application/json'}
838
+ # res = Net::HTTP.post(_uri, data, headers) # => #<Net::HTTPCreated 201 Created readbody=true>
839
+ # puts res.body
840
+ #
841
+ # Output:
506
842
  #
507
- # require 'net/http'
508
- # require 'uri'
843
+ # {
844
+ # "title": "foo",
845
+ # "body": "bar",
846
+ # "userId": 1,
847
+ # "id": 101
848
+ # }
509
849
  #
510
- # Net::HTTP.post URI('http://www.example.com/api/search'),
511
- # { "q" => "ruby", "max" => "50" }.to_json,
512
- # "Content-Type" => "application/json"
850
+ # Related:
851
+ #
852
+ # - Net::HTTP::Post: request class for \HTTP method +POST+.
853
+ # - Net::HTTP#post: convenience method for \HTTP method +POST+.
513
854
  #
514
855
  def HTTP.post(url, data, header = nil)
515
856
  start(url.hostname, url.port,
@@ -518,23 +859,25 @@ module Net #:nodoc:
518
859
  }
519
860
  end
520
861
 
521
- # Posts HTML form data to the specified URI object.
522
- # The form data must be provided as a Hash mapping from String to String.
523
- # Example:
862
+ # Posts data to a host; returns a Net::HTTPResponse object.
524
863
  #
525
- # { "cmd" => "search", "q" => "ruby", "max" => "50" }
864
+ # Argument +url+ must be a URI;
865
+ # argument +data+ must be a hash:
526
866
  #
527
- # This method also does Basic Authentication iff +url+.user exists.
528
- # But userinfo for authentication is deprecated (RFC3986).
529
- # So this feature will be removed.
530
- #
531
- # Example:
867
+ # _uri = uri.dup
868
+ # _uri.path = '/posts'
869
+ # data = {title: 'foo', body: 'bar', userId: 1}
870
+ # res = Net::HTTP.post_form(_uri, data) # => #<Net::HTTPCreated 201 Created readbody=true>
871
+ # puts res.body
532
872
  #
533
- # require 'net/http'
534
- # require 'uri'
873
+ # Output:
535
874
  #
536
- # Net::HTTP.post_form URI('http://www.example.com/search.cgi'),
537
- # { "q" => "ruby", "max" => "50" }
875
+ # {
876
+ # "title": "foo",
877
+ # "body": "bar",
878
+ # "userId": "1",
879
+ # "id": 101
880
+ # }
538
881
  #
539
882
  def HTTP.post_form(url, params)
540
883
  req = Post.new(url)
@@ -547,20 +890,29 @@ module Net #:nodoc:
547
890
  end
548
891
 
549
892
  #
550
- # HTTP session management
893
+ # \HTTP session management
551
894
  #
552
895
 
553
- # The default port to use for HTTP requests; defaults to 80.
896
+ # Returns integer +80+, the default port to use for \HTTP requests:
897
+ #
898
+ # Net::HTTP.default_port # => 80
899
+ #
554
900
  def HTTP.default_port
555
901
  http_default_port()
556
902
  end
557
903
 
558
- # The default port to use for HTTP requests; defaults to 80.
904
+ # Returns integer +80+, the default port to use for \HTTP requests:
905
+ #
906
+ # Net::HTTP.http_default_port # => 80
907
+ #
559
908
  def HTTP.http_default_port
560
909
  80
561
910
  end
562
911
 
563
- # The default port to use for HTTPS requests; defaults to 443.
912
+ # Returns integer +443+, the default port to use for HTTPS requests:
913
+ #
914
+ # Net::HTTP.https_default_port # => 443
915
+ #
564
916
  def HTTP.https_default_port
565
917
  443
566
918
  end
@@ -570,35 +922,91 @@ module Net #:nodoc:
570
922
  end
571
923
 
572
924
  # :call-seq:
573
- # HTTP.start(address, port, p_addr, p_port, p_user, p_pass, &block)
574
- # HTTP.start(address, port=nil, p_addr=:ENV, p_port=nil, p_user=nil, p_pass=nil, opt, &block)
575
- #
576
- # Creates a new Net::HTTP object, then additionally opens the TCP
577
- # connection and HTTP session.
578
- #
579
- # Arguments are the following:
580
- # _address_ :: hostname or IP address of the server
581
- # _port_ :: port of the server
582
- # _p_addr_ :: address of proxy
583
- # _p_port_ :: port of proxy
584
- # _p_user_ :: user of proxy
585
- # _p_pass_ :: pass of proxy
586
- # _opt_ :: optional hash
587
- #
588
- # _opt_ sets following values by its accessor.
589
- # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers, keep_alive_timeout,
590
- # close_on_empty_response, key, open_timeout, read_timeout, write_timeout, ssl_timeout,
591
- # ssl_version, use_ssl, verify_callback, verify_depth and verify_mode.
592
- # If you set :use_ssl as true, you can use https and default value of
593
- # verify_mode is set as OpenSSL::SSL::VERIFY_PEER.
594
- #
595
- # If the optional block is given, the newly
596
- # created Net::HTTP object is passed to it and closed when the
597
- # block finishes. In this case, the return value of this method
598
- # is the return value of the block. If no block is given, the
599
- # return value of this method is the newly created Net::HTTP object
600
- # itself, and the caller is responsible for closing it upon completion
601
- # using the finish() method.
925
+ # HTTP.start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) -> http
926
+ # HTTP.start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) {|http| ... } -> object
927
+ #
928
+ # Creates a new \Net::HTTP object, +http+, via \Net::HTTP.new:
929
+ #
930
+ # - For arguments +address+ and +port+, see Net::HTTP.new.
931
+ # - For proxy-defining arguments +p_addr+ through +p_pass+,
932
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
933
+ # - For argument +opts+, see below.
934
+ #
935
+ # With no block given:
936
+ #
937
+ # - Calls <tt>http.start</tt> with no block (see #start),
938
+ # which opens a TCP connection and \HTTP session.
939
+ # - Returns +http+.
940
+ # - The caller should call #finish to close the session:
941
+ #
942
+ # http = Net::HTTP.start(hostname)
943
+ # http.started? # => true
944
+ # http.finish
945
+ # http.started? # => false
946
+ #
947
+ # With a block given:
948
+ #
949
+ # - Calls <tt>http.start</tt> with the block (see #start), which:
950
+ #
951
+ # - Opens a TCP connection and \HTTP session.
952
+ # - Calls the block,
953
+ # which may make any number of requests to the host.
954
+ # - Closes the \HTTP session and TCP connection on block exit.
955
+ # - Returns the block's value +object+.
956
+ #
957
+ # - Returns +object+.
958
+ #
959
+ # Example:
960
+ #
961
+ # hostname = 'jsonplaceholder.typicode.com'
962
+ # Net::HTTP.start(hostname) do |http|
963
+ # puts http.get('/todos/1').body
964
+ # puts http.get('/todos/2').body
965
+ # end
966
+ #
967
+ # Output:
968
+ #
969
+ # {
970
+ # "userId": 1,
971
+ # "id": 1,
972
+ # "title": "delectus aut autem",
973
+ # "completed": false
974
+ # }
975
+ # {
976
+ # "userId": 1,
977
+ # "id": 2,
978
+ # "title": "quis ut nam facilis et officia qui",
979
+ # "completed": false
980
+ # }
981
+ #
982
+ # If the last argument given is a hash, it is the +opts+ hash,
983
+ # where each key is a method or accessor to be called,
984
+ # and its value is the value to be set.
985
+ #
986
+ # The keys may include:
987
+ #
988
+ # - #ca_file
989
+ # - #ca_path
990
+ # - #cert
991
+ # - #cert_store
992
+ # - #ciphers
993
+ # - #close_on_empty_response
994
+ # - +ipaddr+ (calls #ipaddr=)
995
+ # - #keep_alive_timeout
996
+ # - #key
997
+ # - #open_timeout
998
+ # - #read_timeout
999
+ # - #ssl_timeout
1000
+ # - #ssl_version
1001
+ # - +use_ssl+ (calls #use_ssl=)
1002
+ # - #verify_callback
1003
+ # - #verify_depth
1004
+ # - #verify_mode
1005
+ # - #write_timeout
1006
+ #
1007
+ # Note: If +port+ is +nil+ and <tt>opts[:use_ssl]</tt> is a truthy value,
1008
+ # the value passed to +new+ is Net::HTTP.https_default_port, not +port+.
1009
+ #
602
1010
  def HTTP.start(address, *arg, &block) # :yield: +http+
603
1011
  arg.pop if opt = Hash.try_convert(arg[-1])
604
1012
  port, p_addr, p_port, p_user, p_pass = *arg
@@ -625,25 +1033,34 @@ module Net #:nodoc:
625
1033
  alias newobj new # :nodoc:
626
1034
  end
627
1035
 
628
- # Creates a new Net::HTTP object without opening a TCP connection or
629
- # HTTP session.
1036
+ # Returns a new \Net::HTTP object +http+
1037
+ # (but does not open a TCP connection or \HTTP session).
630
1038
  #
631
- # The +address+ should be a DNS hostname or IP address, the +port+ is the
632
- # port the server operates on. If no +port+ is given the default port for
633
- # HTTP or HTTPS is used.
1039
+ # With only string argument +address+ given
1040
+ # (and <tt>ENV['http_proxy']</tt> undefined or +nil+),
1041
+ # the returned +http+:
634
1042
  #
635
- # If none of the +p_+ arguments are given, the proxy host and port are
636
- # taken from the +http_proxy+ environment variable (or its uppercase
637
- # equivalent) if present. If the proxy requires authentication you must
638
- # supply it by hand. See URI::Generic#find_proxy for details of proxy
639
- # detection from the environment. To disable proxy detection set +p_addr+
640
- # to nil.
1043
+ # - Has the given address.
1044
+ # - Has the default port number, Net::HTTP.default_port (80).
1045
+ # - Has no proxy.
641
1046
  #
642
- # If you are connecting to a custom proxy, +p_addr+ specifies the DNS name
643
- # or IP address of the proxy host, +p_port+ the port to use to access the
644
- # proxy, +p_user+ and +p_pass+ the username and password if authorization
645
- # is required to use the proxy, and p_no_proxy hosts which do not
646
- # use the proxy.
1047
+ # Example:
1048
+ #
1049
+ # http = Net::HTTP.new(hostname)
1050
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
1051
+ # http.address # => "jsonplaceholder.typicode.com"
1052
+ # http.port # => 80
1053
+ # http.proxy? # => false
1054
+ #
1055
+ # With integer argument +port+ also given,
1056
+ # the returned +http+ has the given port:
1057
+ #
1058
+ # http = Net::HTTP.new(hostname, 8000)
1059
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:8000 open=false>
1060
+ # http.port # => 8000
1061
+ #
1062
+ # For proxy-defining arguments +p_addr+ through +p_no_proxy+,
1063
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
647
1064
  #
648
1065
  def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
649
1066
  http = super address, port
@@ -657,7 +1074,7 @@ module Net #:nodoc:
657
1074
  elsif p_addr == :ENV then
658
1075
  http.proxy_from_env = true
659
1076
  else
660
- if p_addr && p_no_proxy && !URI::Generic.use_proxy?(p_addr, p_addr, p_port, p_no_proxy)
1077
+ if p_addr && p_no_proxy && !URI::Generic.use_proxy?(address, address, port, p_no_proxy)
661
1078
  p_addr = nil
662
1079
  p_port = nil
663
1080
  end
@@ -670,10 +1087,10 @@ module Net #:nodoc:
670
1087
  http
671
1088
  end
672
1089
 
673
- # Creates a new Net::HTTP object for the specified server address,
674
- # without opening the TCP connection or initializing the HTTP session.
1090
+ # Creates a new \Net::HTTP object for the specified server address,
1091
+ # without opening the TCP connection or initializing the \HTTP session.
675
1092
  # The +address+ should be a DNS hostname or IP address.
676
- def initialize(address, port = nil)
1093
+ def initialize(address, port = nil) # :nodoc:
677
1094
  @address = address
678
1095
  @port = (port || HTTP.default_port)
679
1096
  @ipaddr = nil
@@ -691,6 +1108,8 @@ module Net #:nodoc:
691
1108
  @continue_timeout = nil
692
1109
  @max_retries = 1
693
1110
  @debug_output = nil
1111
+ @response_body_encoding = false
1112
+ @ignore_eof = true
694
1113
 
695
1114
  @proxy_from_env = false
696
1115
  @proxy_uri = nil
@@ -708,6 +1127,11 @@ module Net #:nodoc:
708
1127
  end
709
1128
  end
710
1129
 
1130
+ # Returns a string representation of +self+:
1131
+ #
1132
+ # Net::HTTP.new(hostname).inspect
1133
+ # # => "#<Net::HTTP jsonplaceholder.typicode.com:80 open=false>"
1134
+ #
711
1135
  def inspect
712
1136
  "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
713
1137
  end
@@ -715,71 +1139,184 @@ module Net #:nodoc:
715
1139
  # *WARNING* This method opens a serious security hole.
716
1140
  # Never use this method in production code.
717
1141
  #
718
- # Sets an output stream for debugging.
1142
+ # Sets the output stream for debugging:
719
1143
  #
720
1144
  # http = Net::HTTP.new(hostname)
721
- # http.set_debug_output $stderr
722
- # http.start { .... }
1145
+ # File.open('t.tmp', 'w') do |file|
1146
+ # http.set_debug_output(file)
1147
+ # http.start
1148
+ # http.get('/nosuch/1')
1149
+ # http.finish
1150
+ # end
1151
+ # puts File.read('t.tmp')
1152
+ #
1153
+ # Output:
1154
+ #
1155
+ # opening connection to jsonplaceholder.typicode.com:80...
1156
+ # opened
1157
+ # <- "GET /nosuch/1 HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: jsonplaceholder.typicode.com\r\n\r\n"
1158
+ # -> "HTTP/1.1 404 Not Found\r\n"
1159
+ # -> "Date: Mon, 12 Dec 2022 21:14:11 GMT\r\n"
1160
+ # -> "Content-Type: application/json; charset=utf-8\r\n"
1161
+ # -> "Content-Length: 2\r\n"
1162
+ # -> "Connection: keep-alive\r\n"
1163
+ # -> "X-Powered-By: Express\r\n"
1164
+ # -> "X-Ratelimit-Limit: 1000\r\n"
1165
+ # -> "X-Ratelimit-Remaining: 999\r\n"
1166
+ # -> "X-Ratelimit-Reset: 1670879660\r\n"
1167
+ # -> "Vary: Origin, Accept-Encoding\r\n"
1168
+ # -> "Access-Control-Allow-Credentials: true\r\n"
1169
+ # -> "Cache-Control: max-age=43200\r\n"
1170
+ # -> "Pragma: no-cache\r\n"
1171
+ # -> "Expires: -1\r\n"
1172
+ # -> "X-Content-Type-Options: nosniff\r\n"
1173
+ # -> "Etag: W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"\r\n"
1174
+ # -> "Via: 1.1 vegur\r\n"
1175
+ # -> "CF-Cache-Status: MISS\r\n"
1176
+ # -> "Server-Timing: cf-q-config;dur=1.3000000762986e-05\r\n"
1177
+ # -> "Report-To: {\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=yOr40jo%2BwS1KHzhTlVpl54beJ5Wx2FcG4gGV0XVrh3X9OlR5q4drUn2dkt5DGO4GDcE%2BVXT7CNgJvGs%2BZleIyMu8CLieFiDIvOviOY3EhHg94m0ZNZgrEdpKD0S85S507l1vsEwEHkoTm%2Ff19SiO\"}],\"group\":\"cf-nel\",\"max_age\":604800}\r\n"
1178
+ # -> "NEL: {\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}\r\n"
1179
+ # -> "Server: cloudflare\r\n"
1180
+ # -> "CF-RAY: 778977dc484ce591-DFW\r\n"
1181
+ # -> "alt-svc: h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400\r\n"
1182
+ # -> "\r\n"
1183
+ # reading 2 bytes...
1184
+ # -> "{}"
1185
+ # read 2 bytes
1186
+ # Conn keep-alive
723
1187
  #
724
1188
  def set_debug_output(output)
725
1189
  warn 'Net::HTTP#set_debug_output called after HTTP started', uplevel: 1 if started?
726
1190
  @debug_output = output
727
1191
  end
728
1192
 
729
- # The DNS host name or IP address to connect to.
1193
+ # Returns the string host name or host IP given as argument +address+ in ::new.
730
1194
  attr_reader :address
731
1195
 
732
- # The port number to connect to.
1196
+ # Returns the integer port number given as argument +port+ in ::new.
733
1197
  attr_reader :port
734
1198
 
735
- # The local host used to establish the connection.
1199
+ # Sets or returns the string local host used to establish the connection;
1200
+ # initially +nil+.
736
1201
  attr_accessor :local_host
737
1202
 
738
- # The local port used to establish the connection.
1203
+ # Sets or returns the integer local port used to establish the connection;
1204
+ # initially +nil+.
739
1205
  attr_accessor :local_port
740
1206
 
1207
+ # Returns the encoding to use for the response body;
1208
+ # see #response_body_encoding=.
1209
+ attr_reader :response_body_encoding
1210
+
1211
+ # Sets the encoding to be used for the response body;
1212
+ # returns the encoding.
1213
+ #
1214
+ # The given +value+ may be:
1215
+ #
1216
+ # - An Encoding object.
1217
+ # - The name of an encoding.
1218
+ # - An alias for an encoding name.
1219
+ #
1220
+ # See {Encoding}[https://docs.ruby-lang.org/en/master/Encoding.html].
1221
+ #
1222
+ # Examples:
1223
+ #
1224
+ # http = Net::HTTP.new(hostname)
1225
+ # http.response_body_encoding = Encoding::US_ASCII # => #<Encoding:US-ASCII>
1226
+ # http.response_body_encoding = 'US-ASCII' # => "US-ASCII"
1227
+ # http.response_body_encoding = 'ASCII' # => "ASCII"
1228
+ #
1229
+ def response_body_encoding=(value)
1230
+ value = Encoding.find(value) if value.is_a?(String)
1231
+ @response_body_encoding = value
1232
+ end
1233
+
1234
+ # Sets whether to determine the proxy from environment variable
1235
+ # '<tt>ENV['http_proxy']</tt>';
1236
+ # see {Proxy Using ENV['http_proxy']}[rdoc-ref:Net::HTTP@Proxy+Using+-27ENV-5B-27http_proxy-27-5D-27].
741
1237
  attr_writer :proxy_from_env
1238
+
1239
+ # Sets the proxy address;
1240
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
742
1241
  attr_writer :proxy_address
1242
+
1243
+ # Sets the proxy port;
1244
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
743
1245
  attr_writer :proxy_port
1246
+
1247
+ # Sets the proxy user;
1248
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
744
1249
  attr_writer :proxy_user
1250
+
1251
+ # Sets the proxy password;
1252
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
745
1253
  attr_writer :proxy_pass
746
1254
 
747
- # The IP address to connect to/used to connect to
1255
+ # Returns the IP address for the connection.
1256
+ #
1257
+ # If the session has not been started,
1258
+ # returns the value set by #ipaddr=,
1259
+ # or +nil+ if it has not been set:
1260
+ #
1261
+ # http = Net::HTTP.new(hostname)
1262
+ # http.ipaddr # => nil
1263
+ # http.ipaddr = '172.67.155.76'
1264
+ # http.ipaddr # => "172.67.155.76"
1265
+ #
1266
+ # If the session has been started,
1267
+ # returns the IP address from the socket:
1268
+ #
1269
+ # http = Net::HTTP.new(hostname)
1270
+ # http.start
1271
+ # http.ipaddr # => "172.67.155.76"
1272
+ # http.finish
1273
+ #
748
1274
  def ipaddr
749
1275
  started? ? @socket.io.peeraddr[3] : @ipaddr
750
1276
  end
751
1277
 
752
- # Set the IP address to connect to
1278
+ # Sets the IP address for the connection:
1279
+ #
1280
+ # http = Net::HTTP.new(hostname)
1281
+ # http.ipaddr # => nil
1282
+ # http.ipaddr = '172.67.155.76'
1283
+ # http.ipaddr # => "172.67.155.76"
1284
+ #
1285
+ # The IP address may not be set if the session has been started.
753
1286
  def ipaddr=(addr)
754
1287
  raise IOError, "ipaddr value changed, but session already started" if started?
755
1288
  @ipaddr = addr
756
1289
  end
757
1290
 
758
- # Number of seconds to wait for the connection to open. Any number
759
- # may be used, including Floats for fractional seconds. If the HTTP
760
- # object cannot open a connection in this many seconds, it raises a
761
- # Net::OpenTimeout exception. The default value is 60 seconds.
1291
+ # Sets or returns the numeric (\Integer or \Float) number of seconds
1292
+ # to wait for a connection to open;
1293
+ # initially 60.
1294
+ # If the connection is not made in the given interval,
1295
+ # an exception is raised.
762
1296
  attr_accessor :open_timeout
763
1297
 
764
- # Number of seconds to wait for one block to be read (via one read(2)
765
- # call). Any number may be used, including Floats for fractional
766
- # seconds. If the HTTP object cannot read data in this many seconds,
767
- # it raises a Net::ReadTimeout exception. The default value is 60 seconds.
1298
+ # Returns the numeric (\Integer or \Float) number of seconds
1299
+ # to wait for one block to be read (via one read(2) call);
1300
+ # see #read_timeout=.
768
1301
  attr_reader :read_timeout
769
1302
 
770
- # Number of seconds to wait for one block to be written (via one write(2)
771
- # call). Any number may be used, including Floats for fractional
772
- # seconds. If the HTTP object cannot write data in this many seconds,
773
- # it raises a Net::WriteTimeout exception. The default value is 60 seconds.
774
- # Net::WriteTimeout is not raised on Windows.
1303
+ # Returns the numeric (\Integer or \Float) number of seconds
1304
+ # to wait for one block to be written (via one write(2) call);
1305
+ # see #write_timeout=.
775
1306
  attr_reader :write_timeout
776
1307
 
777
- # Maximum number of times to retry an idempotent request in case of
778
- # Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET,
1308
+ # Sets the maximum number of times to retry an idempotent request in case of
1309
+ # \Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET,
779
1310
  # Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError,
780
1311
  # Timeout::Error.
781
- # Should be a non-negative integer number. Zero means no retries.
782
- # The default value is 1.
1312
+ # The initial value is 1.
1313
+ #
1314
+ # Argument +retries+ must be a non-negative numeric value:
1315
+ #
1316
+ # http = Net::HTTP.new(hostname)
1317
+ # http.max_retries = 2 # => 2
1318
+ # http.max_retries # => 2
1319
+ #
783
1320
  def max_retries=(retries)
784
1321
  retries = retries.to_int
785
1322
  if retries < 0
@@ -788,55 +1325,113 @@ module Net #:nodoc:
788
1325
  @max_retries = retries
789
1326
  end
790
1327
 
1328
+ # Returns the maximum number of times to retry an idempotent request;
1329
+ # see #max_retries=.
791
1330
  attr_reader :max_retries
792
1331
 
793
- # Setter for the read_timeout attribute.
1332
+ # Sets the read timeout, in seconds, for +self+ to integer +sec+;
1333
+ # the initial value is 60.
1334
+ #
1335
+ # Argument +sec+ must be a non-negative numeric value:
1336
+ #
1337
+ # http = Net::HTTP.new(hostname)
1338
+ # http.read_timeout # => 60
1339
+ # http.get('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
1340
+ # http.read_timeout = 0
1341
+ # http.get('/todos/1') # Raises Net::ReadTimeout.
1342
+ #
794
1343
  def read_timeout=(sec)
795
1344
  @socket.read_timeout = sec if @socket
796
1345
  @read_timeout = sec
797
1346
  end
798
1347
 
799
- # Setter for the write_timeout attribute.
1348
+ # Sets the write timeout, in seconds, for +self+ to integer +sec+;
1349
+ # the initial value is 60.
1350
+ #
1351
+ # Argument +sec+ must be a non-negative numeric value:
1352
+ #
1353
+ # _uri = uri.dup
1354
+ # _uri.path = '/posts'
1355
+ # body = 'bar' * 200000
1356
+ # data = <<EOF
1357
+ # {"title": "foo", "body": "#{body}", "userId": "1"}
1358
+ # EOF
1359
+ # headers = {'content-type': 'application/json'}
1360
+ # http = Net::HTTP.new(hostname)
1361
+ # http.write_timeout # => 60
1362
+ # http.post(_uri.path, data, headers)
1363
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
1364
+ # http.write_timeout = 0
1365
+ # http.post(_uri.path, data, headers) # Raises Net::WriteTimeout.
1366
+ #
800
1367
  def write_timeout=(sec)
801
1368
  @socket.write_timeout = sec if @socket
802
1369
  @write_timeout = sec
803
1370
  end
804
1371
 
805
- # Seconds to wait for 100 Continue response. If the HTTP object does not
806
- # receive a response in this many seconds it sends the request body. The
807
- # default value is +nil+.
1372
+ # Returns the continue timeout value;
1373
+ # see continue_timeout=.
808
1374
  attr_reader :continue_timeout
809
1375
 
810
- # Setter for the continue_timeout attribute.
1376
+ # Sets the continue timeout value,
1377
+ # which is the number of seconds to wait for an expected 100 Continue response.
1378
+ # If the \HTTP object does not receive a response in this many seconds
1379
+ # it sends the request body.
811
1380
  def continue_timeout=(sec)
812
1381
  @socket.continue_timeout = sec if @socket
813
1382
  @continue_timeout = sec
814
1383
  end
815
1384
 
816
- # Seconds to reuse the connection of the previous request.
817
- # If the idle time is less than this Keep-Alive Timeout,
818
- # Net::HTTP reuses the TCP/IP socket used by the previous communication.
819
- # The default value is 2 seconds.
1385
+ # Sets or returns the numeric (\Integer or \Float) number of seconds
1386
+ # to keep the connection open after a request is sent;
1387
+ # initially 2.
1388
+ # If a new request is made during the given interval,
1389
+ # the still-open connection is used;
1390
+ # otherwise the connection will have been closed
1391
+ # and a new connection is opened.
820
1392
  attr_accessor :keep_alive_timeout
821
1393
 
822
- # Returns true if the HTTP session has been started.
1394
+ # Sets or returns whether to ignore end-of-file when reading a response body
1395
+ # with <tt>Content-Length</tt> headers;
1396
+ # initially +true+.
1397
+ attr_accessor :ignore_eof
1398
+
1399
+ # Returns +true+ if the \HTTP session has been started:
1400
+ #
1401
+ # http = Net::HTTP.new(hostname)
1402
+ # http.started? # => false
1403
+ # http.start
1404
+ # http.started? # => true
1405
+ # http.finish # => nil
1406
+ # http.started? # => false
1407
+ #
1408
+ # Net::HTTP.start(hostname) do |http|
1409
+ # http.started?
1410
+ # end # => true
1411
+ # http.started? # => false
1412
+ #
823
1413
  def started?
824
1414
  @started
825
1415
  end
826
1416
 
827
1417
  alias active? started? #:nodoc: obsolete
828
1418
 
1419
+ # Sets or returns whether to close the connection when the response is empty;
1420
+ # initially +false+.
829
1421
  attr_accessor :close_on_empty_response
830
1422
 
831
- # Returns true if SSL/TLS is being used with HTTP.
1423
+ # Returns +true+ if +self+ uses SSL, +false+ otherwise.
1424
+ # See Net::HTTP#use_ssl=.
832
1425
  def use_ssl?
833
1426
  @use_ssl
834
1427
  end
835
1428
 
836
- # Turn on/off SSL.
837
- # This flag must be set before starting session.
838
- # If you change use_ssl value after session started,
839
- # a Net::HTTP object raises IOError.
1429
+ # Sets whether a new session is to use
1430
+ # {Transport Layer Security}[https://en.wikipedia.org/wiki/Transport_Layer_Security]:
1431
+ #
1432
+ # Raises IOError if attempting to change during a session.
1433
+ #
1434
+ # Raises OpenSSL::SSL::SSLError if the port is not an HTTPS port.
840
1435
  def use_ssl=(flag)
841
1436
  flag = flag ? true : false
842
1437
  if started? and @use_ssl != flag
@@ -861,7 +1456,7 @@ module Net #:nodoc:
861
1456
  :@verify_depth,
862
1457
  :@verify_mode,
863
1458
  :@verify_hostname,
864
- ]
1459
+ ] # :nodoc:
865
1460
  SSL_ATTRIBUTES = [
866
1461
  :ca_file,
867
1462
  :ca_path,
@@ -878,64 +1473,67 @@ module Net #:nodoc:
878
1473
  :verify_depth,
879
1474
  :verify_mode,
880
1475
  :verify_hostname,
881
- ]
1476
+ ] # :nodoc:
882
1477
 
883
- # Sets path of a CA certification file in PEM format.
884
- #
885
- # The file can contain several CA certificates.
1478
+ # Sets or returns the path to a CA certification file in PEM format.
886
1479
  attr_accessor :ca_file
887
1480
 
888
- # Sets path of a CA certification directory containing certifications in
889
- # PEM format.
1481
+ # Sets or returns the path of to CA directory
1482
+ # containing certification files in PEM format.
890
1483
  attr_accessor :ca_path
891
1484
 
892
- # Sets an OpenSSL::X509::Certificate object as client certificate.
893
- # (This method is appeared in Michal Rokos's OpenSSL extension).
1485
+ # Sets or returns the OpenSSL::X509::Certificate object
1486
+ # to be used for client certification.
894
1487
  attr_accessor :cert
895
1488
 
896
- # Sets the X509::Store to verify peer certificate.
1489
+ # Sets or returns the X509::Store to be used for verifying peer certificate.
897
1490
  attr_accessor :cert_store
898
1491
 
899
- # Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers=
1492
+ # Sets or returns the available SSL ciphers.
1493
+ # See {OpenSSL::SSL::SSLContext#ciphers=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ciphers-3D].
900
1494
  attr_accessor :ciphers
901
1495
 
902
- # Sets the extra X509 certificates to be added to the certificate chain.
903
- # See OpenSSL::SSL::SSLContext#extra_chain_cert=
1496
+ # Sets or returns the extra X509 certificates to be added to the certificate chain.
1497
+ # See {OpenSSL::SSL::SSLContext#add_certificate}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-add_certificate].
904
1498
  attr_accessor :extra_chain_cert
905
1499
 
906
- # Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
907
- # (This method is appeared in Michal Rokos's OpenSSL extension.)
1500
+ # Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
908
1501
  attr_accessor :key
909
1502
 
910
- # Sets the SSL timeout seconds.
1503
+ # Sets or returns the SSL timeout seconds.
911
1504
  attr_accessor :ssl_timeout
912
1505
 
913
- # Sets the SSL version. See OpenSSL::SSL::SSLContext#ssl_version=
1506
+ # Sets or returns the SSL version.
1507
+ # See {OpenSSL::SSL::SSLContext#ssl_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D].
914
1508
  attr_accessor :ssl_version
915
1509
 
916
- # Sets the minimum SSL version. See OpenSSL::SSL::SSLContext#min_version=
1510
+ # Sets or returns the minimum SSL version.
1511
+ # See {OpenSSL::SSL::SSLContext#min_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D].
917
1512
  attr_accessor :min_version
918
1513
 
919
- # Sets the maximum SSL version. See OpenSSL::SSL::SSLContext#max_version=
1514
+ # Sets or returns the maximum SSL version.
1515
+ # See {OpenSSL::SSL::SSLContext#max_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D].
920
1516
  attr_accessor :max_version
921
1517
 
922
- # Sets the verify callback for the server certification verification.
1518
+ # Sets or returns the callback for the server certification verification.
923
1519
  attr_accessor :verify_callback
924
1520
 
925
- # Sets the maximum depth for the certificate chain verification.
1521
+ # Sets or returns the maximum depth for the certificate chain verification.
926
1522
  attr_accessor :verify_depth
927
1523
 
928
- # Sets the flags for server the certification verification at beginning of
929
- # SSL/TLS session.
930
- #
1524
+ # Sets or returns the flags for server the certification verification
1525
+ # at the beginning of the SSL/TLS session.
931
1526
  # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable.
932
1527
  attr_accessor :verify_mode
933
1528
 
934
- # Sets to check the server certificate is valid for the hostname.
935
- # See OpenSSL::SSL::SSLContext#verify_hostname=
1529
+ # Sets or returns whether to verify that the server certificate is valid
1530
+ # for the hostname.
1531
+ # See {OpenSSL::SSL::SSLContext#verify_hostname=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-verify_mode].
936
1532
  attr_accessor :verify_hostname
937
1533
 
938
- # Returns the X.509 certificates the server presented.
1534
+ # Returns the X509 certificate chain (an array of strings)
1535
+ # for the session's socket peer,
1536
+ # or +nil+ if none.
939
1537
  def peer_cert
940
1538
  if not use_ssl? or not @socket
941
1539
  return nil
@@ -943,14 +1541,26 @@ module Net #:nodoc:
943
1541
  @socket.io.peer_cert
944
1542
  end
945
1543
 
946
- # Opens a TCP connection and HTTP session.
1544
+ # Starts an \HTTP session.
947
1545
  #
948
- # When this method is called with a block, it passes the Net::HTTP
949
- # object to the block, and closes the TCP connection and HTTP session
950
- # after the block has been executed.
1546
+ # Without a block, returns +self+:
951
1547
  #
952
- # When called with a block, it returns the return value of the
953
- # block; otherwise, it returns self.
1548
+ # http = Net::HTTP.new(hostname)
1549
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
1550
+ # http.start
1551
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=true>
1552
+ # http.started? # => true
1553
+ # http.finish
1554
+ #
1555
+ # With a block, calls the block with +self+,
1556
+ # finishes the session when the block exits,
1557
+ # and returns the block's value:
1558
+ #
1559
+ # http.start do |http|
1560
+ # http
1561
+ # end
1562
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
1563
+ # http.started? # => false
954
1564
  #
955
1565
  def start # :yield: http
956
1566
  raise IOError, 'HTTP session already opened' if @started
@@ -973,6 +1583,12 @@ module Net #:nodoc:
973
1583
  private :do_start
974
1584
 
975
1585
  def connect
1586
+ if use_ssl?
1587
+ # reference early to load OpenSSL before connecting,
1588
+ # as OpenSSL may take time to load.
1589
+ @ssl_context = OpenSSL::SSL::SSLContext.new
1590
+ end
1591
+
976
1592
  if proxy? then
977
1593
  conn_addr = proxy_address
978
1594
  conn_port = proxy_port
@@ -981,7 +1597,7 @@ module Net #:nodoc:
981
1597
  conn_port = port
982
1598
  end
983
1599
 
984
- D "opening connection to #{conn_addr}:#{conn_port}..."
1600
+ debug "opening connection to #{conn_addr}:#{conn_port}..."
985
1601
  s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
986
1602
  begin
987
1603
  TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
@@ -991,15 +1607,15 @@ module Net #:nodoc:
991
1607
  end
992
1608
  }
993
1609
  s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
994
- D "opened"
1610
+ debug "opened"
995
1611
  if use_ssl?
996
1612
  if proxy?
997
1613
  plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
998
1614
  write_timeout: @write_timeout,
999
1615
  continue_timeout: @continue_timeout,
1000
1616
  debug_output: @debug_output)
1001
- buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
1002
- buf << "Host: #{@address}:#{@port}\r\n"
1617
+ buf = +"CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n" \
1618
+ "Host: #{@address}:#{@port}\r\n"
1003
1619
  if proxy_user
1004
1620
  credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0')
1005
1621
  buf << "Proxy-Authorization: Basic #{credential}\r\n"
@@ -1020,35 +1636,56 @@ module Net #:nodoc:
1020
1636
  end
1021
1637
  end
1022
1638
  end
1023
- @ssl_context = OpenSSL::SSL::SSLContext.new
1024
1639
  @ssl_context.set_params(ssl_parameters)
1025
- @ssl_context.session_cache_mode =
1026
- OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
1027
- OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
1028
- @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1029
- D "starting SSL for #{conn_addr}:#{conn_port}..."
1640
+ unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
1641
+ @ssl_context.session_cache_mode =
1642
+ OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
1643
+ OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
1644
+ end
1645
+ if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
1646
+ @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1647
+ end
1648
+
1649
+ # Still do the post_connection_check below even if connecting
1650
+ # to IP address
1651
+ verify_hostname = @ssl_context.verify_hostname
1652
+
1653
+ # Server Name Indication (SNI) RFC 3546/6066
1654
+ case @address
1655
+ when Resolv::IPv4::Regex, Resolv::IPv6::Regex
1656
+ # don't set SNI, as IP addresses in SNI is not valid
1657
+ # per RFC 6066, section 3.
1658
+
1659
+ # Avoid openssl warning
1660
+ @ssl_context.verify_hostname = false
1661
+ else
1662
+ ssl_host_address = @address
1663
+ end
1664
+
1665
+ debug "starting SSL for #{conn_addr}:#{conn_port}..."
1030
1666
  s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
1031
1667
  s.sync_close = true
1032
- # Server Name Indication (SNI) RFC 3546
1033
- s.hostname = @address if s.respond_to? :hostname=
1668
+ s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
1669
+
1034
1670
  if @ssl_session and
1035
1671
  Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
1036
1672
  s.session = @ssl_session
1037
1673
  end
1038
1674
  ssl_socket_connect(s, @open_timeout)
1039
- if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
1675
+ if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
1040
1676
  s.post_connection_check(@address)
1041
1677
  end
1042
- D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1678
+ debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1043
1679
  end
1044
1680
  @socket = BufferedIO.new(s, read_timeout: @read_timeout,
1045
1681
  write_timeout: @write_timeout,
1046
1682
  continue_timeout: @continue_timeout,
1047
1683
  debug_output: @debug_output)
1684
+ @last_communicated = nil
1048
1685
  on_connect
1049
1686
  rescue => exception
1050
1687
  if s
1051
- D "Conn close because of connect error #{exception}"
1688
+ debug "Conn close because of connect error #{exception}"
1052
1689
  s.close
1053
1690
  end
1054
1691
  raise
@@ -1059,8 +1696,15 @@ module Net #:nodoc:
1059
1696
  end
1060
1697
  private :on_connect
1061
1698
 
1062
- # Finishes the HTTP session and closes the TCP connection.
1063
- # Raises IOError if the session has not been started.
1699
+ # Finishes the \HTTP session:
1700
+ #
1701
+ # http = Net::HTTP.new(hostname)
1702
+ # http.start
1703
+ # http.started? # => true
1704
+ # http.finish # => nil
1705
+ # http.started? # => false
1706
+ #
1707
+ # Raises IOError if not in a session.
1064
1708
  def finish
1065
1709
  raise IOError, 'HTTP session not yet started' unless started?
1066
1710
  do_finish
@@ -1087,12 +1731,12 @@ module Net #:nodoc:
1087
1731
  @proxy_user = nil
1088
1732
  @proxy_pass = nil
1089
1733
 
1090
- # Creates an HTTP proxy class which behaves like Net::HTTP, but
1734
+ # Creates an \HTTP proxy class which behaves like \Net::HTTP, but
1091
1735
  # performs all access via the specified proxy.
1092
1736
  #
1093
1737
  # This class is obsolete. You may pass these same parameters directly to
1094
- # Net::HTTP.new. See Net::HTTP.new for details of the arguments.
1095
- def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil)
1738
+ # \Net::HTTP.new. See Net::HTTP.new for details of the arguments.
1739
+ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc:
1096
1740
  return self unless p_addr
1097
1741
 
1098
1742
  Class.new(self) {
@@ -1114,31 +1758,37 @@ module Net #:nodoc:
1114
1758
  end
1115
1759
 
1116
1760
  class << HTTP
1117
- # returns true if self is a class which was created by HTTP::Proxy.
1761
+ # Returns true if self is a class which was created by HTTP::Proxy.
1118
1762
  def proxy_class?
1119
1763
  defined?(@is_proxy_class) ? @is_proxy_class : false
1120
1764
  end
1121
1765
 
1122
- # Address of proxy host. If Net::HTTP does not use a proxy, nil.
1766
+ # Returns the address of the proxy host, or +nil+ if none;
1767
+ # see Net::HTTP@Proxy+Server.
1123
1768
  attr_reader :proxy_address
1124
1769
 
1125
- # Port number of proxy host. If Net::HTTP does not use a proxy, nil.
1770
+ # Returns the port number of the proxy host, or +nil+ if none;
1771
+ # see Net::HTTP@Proxy+Server.
1126
1772
  attr_reader :proxy_port
1127
1773
 
1128
- # User name for accessing proxy. If Net::HTTP does not use a proxy, nil.
1774
+ # Returns the user name for accessing the proxy, or +nil+ if none;
1775
+ # see Net::HTTP@Proxy+Server.
1129
1776
  attr_reader :proxy_user
1130
1777
 
1131
- # User password for accessing proxy. If Net::HTTP does not use a proxy,
1132
- # nil.
1778
+ # Returns the password for accessing the proxy, or +nil+ if none;
1779
+ # see Net::HTTP@Proxy+Server.
1133
1780
  attr_reader :proxy_pass
1134
1781
  end
1135
1782
 
1136
- # True if requests for this connection will be proxied
1783
+ # Returns +true+ if a proxy server is defined, +false+ otherwise;
1784
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
1137
1785
  def proxy?
1138
1786
  !!(@proxy_from_env ? proxy_uri : @proxy_address)
1139
1787
  end
1140
1788
 
1141
- # True if the proxy for this connection is determined from the environment
1789
+ # Returns +true+ if the proxy server is defined in the environment,
1790
+ # +false+ otherwise;
1791
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
1142
1792
  def proxy_from_env?
1143
1793
  @proxy_from_env
1144
1794
  end
@@ -1147,12 +1797,13 @@ module Net #:nodoc:
1147
1797
  def proxy_uri # :nodoc:
1148
1798
  return if @proxy_uri == false
1149
1799
  @proxy_uri ||= URI::HTTP.new(
1150
- "http".freeze, nil, address, port, nil, nil, nil, nil, nil
1800
+ "http", nil, address, port, nil, nil, nil, nil, nil
1151
1801
  ).find_proxy || false
1152
1802
  @proxy_uri || nil
1153
1803
  end
1154
1804
 
1155
- # The address of the proxy server, if one is configured.
1805
+ # Returns the address of the proxy server, if defined, +nil+ otherwise;
1806
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
1156
1807
  def proxy_address
1157
1808
  if @proxy_from_env then
1158
1809
  proxy_uri&.hostname
@@ -1161,7 +1812,8 @@ module Net #:nodoc:
1161
1812
  end
1162
1813
  end
1163
1814
 
1164
- # The port of the proxy server, if one is configured.
1815
+ # Returns the port number of the proxy server, if defined, +nil+ otherwise;
1816
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
1165
1817
  def proxy_port
1166
1818
  if @proxy_from_env then
1167
1819
  proxy_uri&.port
@@ -1170,26 +1822,23 @@ module Net #:nodoc:
1170
1822
  end
1171
1823
  end
1172
1824
 
1173
- # [Bug #12921]
1174
- if /linux|freebsd|darwin/ =~ RUBY_PLATFORM
1175
- ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = true
1176
- else
1177
- ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = false
1178
- end
1179
-
1180
- # The username of the proxy server, if one is configured.
1825
+ # Returns the user name of the proxy server, if defined, +nil+ otherwise;
1826
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
1181
1827
  def proxy_user
1182
- if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1183
- proxy_uri&.user
1828
+ if @proxy_from_env
1829
+ user = proxy_uri&.user
1830
+ unescape(user) if user
1184
1831
  else
1185
1832
  @proxy_user
1186
1833
  end
1187
1834
  end
1188
1835
 
1189
- # The password of the proxy server, if one is configured.
1836
+ # Returns the password of the proxy server, if defined, +nil+ otherwise;
1837
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
1190
1838
  def proxy_pass
1191
- if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1192
- proxy_uri&.password
1839
+ if @proxy_from_env
1840
+ pass = proxy_uri&.password
1841
+ unescape(pass) if pass
1193
1842
  else
1194
1843
  @proxy_pass
1195
1844
  end
@@ -1200,6 +1849,11 @@ module Net #:nodoc:
1200
1849
 
1201
1850
  private
1202
1851
 
1852
+ def unescape(value)
1853
+ require 'cgi/util'
1854
+ CGI.unescape(value)
1855
+ end
1856
+
1203
1857
  # without proxy, obsolete
1204
1858
 
1205
1859
  def conn_address # :nodoc:
@@ -1228,45 +1882,38 @@ module Net #:nodoc:
1228
1882
 
1229
1883
  public
1230
1884
 
1231
- # Retrieves data from +path+ on the connected-to host which may be an
1232
- # absolute path String or a URI to extract the path from.
1885
+ # :call-seq:
1886
+ # get(path, initheader = nil) {|res| ... }
1887
+ #
1888
+ # Sends a GET request to the server;
1889
+ # returns an instance of a subclass of Net::HTTPResponse.
1233
1890
  #
1234
- # +initheader+ must be a Hash like { 'Accept' => '*/*', ... },
1235
- # and it defaults to an empty hash.
1236
- # If +initheader+ doesn't have the key 'accept-encoding', then
1237
- # a value of "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" is used,
1238
- # so that gzip compression is used in preference to deflate
1239
- # compression, which is used in preference to no compression.
1240
- # Ruby doesn't have libraries to support the compress (Lempel-Ziv)
1241
- # compression, so that is not supported. The intent of this is
1242
- # to reduce bandwidth by default. If this routine sets up
1243
- # compression, then it does the decompression also, removing
1244
- # the header as well to prevent confusion. Otherwise
1245
- # it leaves the body as it found it.
1891
+ # The request is based on the Net::HTTP::Get object
1892
+ # created from string +path+ and initial headers hash +initheader+.
1246
1893
  #
1247
- # This method returns a Net::HTTPResponse object.
1894
+ # With a block given, calls the block with the response body:
1248
1895
  #
1249
- # If called with a block, yields each fragment of the
1250
- # entity body in turn as a string as it is read from
1251
- # the socket. Note that in this case, the returned response
1252
- # object will *not* contain a (meaningful) body.
1896
+ # http = Net::HTTP.new(hostname)
1897
+ # http.get('/todos/1') do |res|
1898
+ # p res
1899
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
1900
+ #
1901
+ # Output:
1253
1902
  #
1254
- # +dest+ argument is obsolete.
1255
- # It still works but you must not use it.
1903
+ # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n}"
1256
1904
  #
1257
- # This method never raises an exception.
1905
+ # With no block given, simply returns the response object:
1258
1906
  #
1259
- # response = http.get('/index.html')
1907
+ # http.get('/') # => #<Net::HTTPOK 200 OK readbody=true>
1260
1908
  #
1261
- # # using block
1262
- # File.open('result.txt', 'w') {|f|
1263
- # http.get('/~foo/') do |str|
1264
- # f.write str
1265
- # end
1266
- # }
1909
+ # Related:
1910
+ #
1911
+ # - Net::HTTP::Get: request class for \HTTP method GET.
1912
+ # - Net::HTTP.get: sends GET request, returns response body.
1267
1913
  #
1268
1914
  def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+
1269
1915
  res = nil
1916
+
1270
1917
  request(Get.new(path, initheader)) {|r|
1271
1918
  r.read_body dest, &block
1272
1919
  res = r
@@ -1274,198 +1921,312 @@ module Net #:nodoc:
1274
1921
  res
1275
1922
  end
1276
1923
 
1277
- # Gets only the header from +path+ on the connected-to host.
1278
- # +header+ is a Hash like { 'Accept' => '*/*', ... }.
1924
+ # Sends a HEAD request to the server;
1925
+ # returns an instance of a subclass of Net::HTTPResponse.
1279
1926
  #
1280
- # This method returns a Net::HTTPResponse object.
1927
+ # The request is based on the Net::HTTP::Head object
1928
+ # created from string +path+ and initial headers hash +initheader+:
1281
1929
  #
1282
- # This method never raises an exception.
1283
- #
1284
- # response = nil
1285
- # Net::HTTP.start('some.www.server', 80) {|http|
1286
- # response = http.head('/index.html')
1287
- # }
1288
- # p response['content-type']
1930
+ # res = http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
1931
+ # res.body # => nil
1932
+ # res.to_hash.take(3)
1933
+ # # =>
1934
+ # [["date", ["Wed, 15 Feb 2023 15:25:42 GMT"]],
1935
+ # ["content-type", ["application/json; charset=utf-8"]],
1936
+ # ["connection", ["close"]]]
1289
1937
  #
1290
1938
  def head(path, initheader = nil)
1291
1939
  request(Head.new(path, initheader))
1292
1940
  end
1293
1941
 
1294
- # Posts +data+ (must be a String) to +path+. +header+ must be a Hash
1295
- # like { 'Accept' => '*/*', ... }.
1942
+ # :call-seq:
1943
+ # post(path, data, initheader = nil) {|res| ... }
1296
1944
  #
1297
- # This method returns a Net::HTTPResponse object.
1945
+ # Sends a POST request to the server;
1946
+ # returns an instance of a subclass of Net::HTTPResponse.
1298
1947
  #
1299
- # If called with a block, yields each fragment of the
1300
- # entity body in turn as a string as it is read from
1301
- # the socket. Note that in this case, the returned response
1302
- # object will *not* contain a (meaningful) body.
1948
+ # The request is based on the Net::HTTP::Post object
1949
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
1303
1950
  #
1304
- # +dest+ argument is obsolete.
1305
- # It still works but you must not use it.
1951
+ # With a block given, calls the block with the response body:
1952
+ #
1953
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
1954
+ # http = Net::HTTP.new(hostname)
1955
+ # http.post('/todos', data) do |res|
1956
+ # p res
1957
+ # end # => #<Net::HTTPCreated 201 Created readbody=true>
1306
1958
  #
1307
- # This method never raises exception.
1959
+ # Output:
1308
1960
  #
1309
- # response = http.post('/cgi-bin/search.rb', 'query=foo')
1961
+ # "{\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\",\n \"id\": 201\n}"
1310
1962
  #
1311
- # # using block
1312
- # File.open('result.txt', 'w') {|f|
1313
- # http.post('/cgi-bin/search.rb', 'query=foo') do |str|
1314
- # f.write str
1315
- # end
1316
- # }
1963
+ # With no block given, simply returns the response object:
1317
1964
  #
1318
- # You should set Content-Type: header field for POST.
1319
- # If no Content-Type: field given, this method uses
1320
- # "application/x-www-form-urlencoded" by default.
1965
+ # http.post('/todos', data) # => #<Net::HTTPCreated 201 Created readbody=true>
1966
+ #
1967
+ # Related:
1968
+ #
1969
+ # - Net::HTTP::Post: request class for \HTTP method POST.
1970
+ # - Net::HTTP.post: sends POST request, returns response body.
1321
1971
  #
1322
1972
  def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
1323
1973
  send_entity(path, data, initheader, dest, Post, &block)
1324
1974
  end
1325
1975
 
1326
- # Sends a PATCH request to the +path+ and gets a response,
1327
- # as an HTTPResponse object.
1976
+ # :call-seq:
1977
+ # patch(path, data, initheader = nil) {|res| ... }
1978
+ #
1979
+ # Sends a PATCH request to the server;
1980
+ # returns an instance of a subclass of Net::HTTPResponse.
1981
+ #
1982
+ # The request is based on the Net::HTTP::Patch object
1983
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
1984
+ #
1985
+ # With a block given, calls the block with the response body:
1986
+ #
1987
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
1988
+ # http = Net::HTTP.new(hostname)
1989
+ # http.patch('/todos/1', data) do |res|
1990
+ # p res
1991
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
1992
+ #
1993
+ # Output:
1994
+ #
1995
+ # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false,\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\"\n}"
1996
+ #
1997
+ # With no block given, simply returns the response object:
1998
+ #
1999
+ # http.patch('/todos/1', data) # => #<Net::HTTPCreated 201 Created readbody=true>
2000
+ #
1328
2001
  def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
1329
2002
  send_entity(path, data, initheader, dest, Patch, &block)
1330
2003
  end
1331
2004
 
1332
- def put(path, data, initheader = nil) #:nodoc:
2005
+ # Sends a PUT request to the server;
2006
+ # returns an instance of a subclass of Net::HTTPResponse.
2007
+ #
2008
+ # The request is based on the Net::HTTP::Put object
2009
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
2010
+ #
2011
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
2012
+ # http = Net::HTTP.new(hostname)
2013
+ # http.put('/todos/1', data) # => #<Net::HTTPOK 200 OK readbody=true>
2014
+ #
2015
+ def put(path, data, initheader = nil)
1333
2016
  request(Put.new(path, initheader), data)
1334
2017
  end
1335
2018
 
1336
- # Sends a PROPPATCH request to the +path+ and gets a response,
1337
- # as an HTTPResponse object.
2019
+ # Sends a PROPPATCH request to the server;
2020
+ # returns an instance of a subclass of Net::HTTPResponse.
2021
+ #
2022
+ # The request is based on the Net::HTTP::Proppatch object
2023
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
2024
+ #
2025
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
2026
+ # http = Net::HTTP.new(hostname)
2027
+ # http.proppatch('/todos/1', data)
2028
+ #
1338
2029
  def proppatch(path, body, initheader = nil)
1339
2030
  request(Proppatch.new(path, initheader), body)
1340
2031
  end
1341
2032
 
1342
- # Sends a LOCK request to the +path+ and gets a response,
1343
- # as an HTTPResponse object.
2033
+ # Sends a LOCK request to the server;
2034
+ # returns an instance of a subclass of Net::HTTPResponse.
2035
+ #
2036
+ # The request is based on the Net::HTTP::Lock object
2037
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
2038
+ #
2039
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
2040
+ # http = Net::HTTP.new(hostname)
2041
+ # http.lock('/todos/1', data)
2042
+ #
1344
2043
  def lock(path, body, initheader = nil)
1345
2044
  request(Lock.new(path, initheader), body)
1346
2045
  end
1347
2046
 
1348
- # Sends a UNLOCK request to the +path+ and gets a response,
1349
- # as an HTTPResponse object.
2047
+ # Sends an UNLOCK request to the server;
2048
+ # returns an instance of a subclass of Net::HTTPResponse.
2049
+ #
2050
+ # The request is based on the Net::HTTP::Unlock object
2051
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
2052
+ #
2053
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
2054
+ # http = Net::HTTP.new(hostname)
2055
+ # http.unlock('/todos/1', data)
2056
+ #
1350
2057
  def unlock(path, body, initheader = nil)
1351
2058
  request(Unlock.new(path, initheader), body)
1352
2059
  end
1353
2060
 
1354
- # Sends a OPTIONS request to the +path+ and gets a response,
1355
- # as an HTTPResponse object.
2061
+ # Sends an Options request to the server;
2062
+ # returns an instance of a subclass of Net::HTTPResponse.
2063
+ #
2064
+ # The request is based on the Net::HTTP::Options object
2065
+ # created from string +path+ and initial headers hash +initheader+.
2066
+ #
2067
+ # http = Net::HTTP.new(hostname)
2068
+ # http.options('/')
2069
+ #
1356
2070
  def options(path, initheader = nil)
1357
2071
  request(Options.new(path, initheader))
1358
2072
  end
1359
2073
 
1360
- # Sends a PROPFIND request to the +path+ and gets a response,
1361
- # as an HTTPResponse object.
2074
+ # Sends a PROPFIND request to the server;
2075
+ # returns an instance of a subclass of Net::HTTPResponse.
2076
+ #
2077
+ # The request is based on the Net::HTTP::Propfind object
2078
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
2079
+ #
2080
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
2081
+ # http = Net::HTTP.new(hostname)
2082
+ # http.propfind('/todos/1', data)
2083
+ #
1362
2084
  def propfind(path, body = nil, initheader = {'Depth' => '0'})
1363
2085
  request(Propfind.new(path, initheader), body)
1364
2086
  end
1365
2087
 
1366
- # Sends a DELETE request to the +path+ and gets a response,
1367
- # as an HTTPResponse object.
2088
+ # Sends a DELETE request to the server;
2089
+ # returns an instance of a subclass of Net::HTTPResponse.
2090
+ #
2091
+ # The request is based on the Net::HTTP::Delete object
2092
+ # created from string +path+ and initial headers hash +initheader+.
2093
+ #
2094
+ # http = Net::HTTP.new(hostname)
2095
+ # http.delete('/todos/1')
2096
+ #
1368
2097
  def delete(path, initheader = {'Depth' => 'Infinity'})
1369
2098
  request(Delete.new(path, initheader))
1370
2099
  end
1371
2100
 
1372
- # Sends a MOVE request to the +path+ and gets a response,
1373
- # as an HTTPResponse object.
2101
+ # Sends a MOVE request to the server;
2102
+ # returns an instance of a subclass of Net::HTTPResponse.
2103
+ #
2104
+ # The request is based on the Net::HTTP::Move object
2105
+ # created from string +path+ and initial headers hash +initheader+.
2106
+ #
2107
+ # http = Net::HTTP.new(hostname)
2108
+ # http.move('/todos/1')
2109
+ #
1374
2110
  def move(path, initheader = nil)
1375
2111
  request(Move.new(path, initheader))
1376
2112
  end
1377
2113
 
1378
- # Sends a COPY request to the +path+ and gets a response,
1379
- # as an HTTPResponse object.
2114
+ # Sends a COPY request to the server;
2115
+ # returns an instance of a subclass of Net::HTTPResponse.
2116
+ #
2117
+ # The request is based on the Net::HTTP::Copy object
2118
+ # created from string +path+ and initial headers hash +initheader+.
2119
+ #
2120
+ # http = Net::HTTP.new(hostname)
2121
+ # http.copy('/todos/1')
2122
+ #
1380
2123
  def copy(path, initheader = nil)
1381
2124
  request(Copy.new(path, initheader))
1382
2125
  end
1383
2126
 
1384
- # Sends a MKCOL request to the +path+ and gets a response,
1385
- # as an HTTPResponse object.
2127
+ # Sends a MKCOL request to the server;
2128
+ # returns an instance of a subclass of Net::HTTPResponse.
2129
+ #
2130
+ # The request is based on the Net::HTTP::Mkcol object
2131
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
2132
+ #
2133
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
2134
+ # http.mkcol('/todos/1', data)
2135
+ # http = Net::HTTP.new(hostname)
2136
+ #
1386
2137
  def mkcol(path, body = nil, initheader = nil)
1387
2138
  request(Mkcol.new(path, initheader), body)
1388
2139
  end
1389
2140
 
1390
- # Sends a TRACE request to the +path+ and gets a response,
1391
- # as an HTTPResponse object.
2141
+ # Sends a TRACE request to the server;
2142
+ # returns an instance of a subclass of Net::HTTPResponse.
2143
+ #
2144
+ # The request is based on the Net::HTTP::Trace object
2145
+ # created from string +path+ and initial headers hash +initheader+.
2146
+ #
2147
+ # http = Net::HTTP.new(hostname)
2148
+ # http.trace('/todos/1')
2149
+ #
1392
2150
  def trace(path, initheader = nil)
1393
2151
  request(Trace.new(path, initheader))
1394
2152
  end
1395
2153
 
1396
- # Sends a GET request to the +path+.
1397
- # Returns the response as a Net::HTTPResponse object.
2154
+ # Sends a GET request to the server;
2155
+ # forms the response into a Net::HTTPResponse object.
2156
+ #
2157
+ # The request is based on the Net::HTTP::Get object
2158
+ # created from string +path+ and initial headers hash +initheader+.
1398
2159
  #
1399
- # When called with a block, passes an HTTPResponse object to the block.
1400
- # The body of the response will not have been read yet;
1401
- # the block can process it using HTTPResponse#read_body,
1402
- # if desired.
2160
+ # With no block given, returns the response object:
1403
2161
  #
1404
- # Returns the response.
2162
+ # http = Net::HTTP.new(hostname)
2163
+ # http.request_get('/todos') # => #<Net::HTTPOK 200 OK readbody=true>
2164
+ #
2165
+ # With a block given, calls the block with the response object
2166
+ # and returns the response object:
1405
2167
  #
1406
- # This method never raises Net::* exceptions.
2168
+ # http.request_get('/todos') do |res|
2169
+ # p res
2170
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
1407
2171
  #
1408
- # response = http.request_get('/index.html')
1409
- # # The entity body is already read in this case.
1410
- # p response['content-type']
1411
- # puts response.body
2172
+ # Output:
1412
2173
  #
1413
- # # Using a block
1414
- # http.request_get('/index.html') {|response|
1415
- # p response['content-type']
1416
- # response.read_body do |str| # read body now
1417
- # print str
1418
- # end
1419
- # }
2174
+ # #<Net::HTTPOK 200 OK readbody=false>
1420
2175
  #
1421
2176
  def request_get(path, initheader = nil, &block) # :yield: +response+
1422
2177
  request(Get.new(path, initheader), &block)
1423
2178
  end
1424
2179
 
1425
- # Sends a HEAD request to the +path+ and returns the response
1426
- # as a Net::HTTPResponse object.
2180
+ # Sends a HEAD request to the server;
2181
+ # returns an instance of a subclass of Net::HTTPResponse.
1427
2182
  #
1428
- # Returns the response.
2183
+ # The request is based on the Net::HTTP::Head object
2184
+ # created from string +path+ and initial headers hash +initheader+.
1429
2185
  #
1430
- # This method never raises Net::* exceptions.
1431
- #
1432
- # response = http.request_head('/index.html')
1433
- # p response['content-type']
2186
+ # http = Net::HTTP.new(hostname)
2187
+ # http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
1434
2188
  #
1435
2189
  def request_head(path, initheader = nil, &block)
1436
2190
  request(Head.new(path, initheader), &block)
1437
2191
  end
1438
2192
 
1439
- # Sends a POST request to the +path+.
2193
+ # Sends a POST request to the server;
2194
+ # forms the response into a Net::HTTPResponse object.
1440
2195
  #
1441
- # Returns the response as a Net::HTTPResponse object.
2196
+ # The request is based on the Net::HTTP::Post object
2197
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
1442
2198
  #
1443
- # When called with a block, the block is passed an HTTPResponse
1444
- # object. The body of that response will not have been read yet;
1445
- # the block can process it using HTTPResponse#read_body, if desired.
2199
+ # With no block given, returns the response object:
1446
2200
  #
1447
- # Returns the response.
2201
+ # http = Net::HTTP.new(hostname)
2202
+ # http.post('/todos', 'xyzzy')
2203
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
2204
+ #
2205
+ # With a block given, calls the block with the response body
2206
+ # and returns the response object:
1448
2207
  #
1449
- # This method never raises Net::* exceptions.
2208
+ # http.post('/todos', 'xyzzy') do |res|
2209
+ # p res
2210
+ # end # => #<Net::HTTPCreated 201 Created readbody=true>
1450
2211
  #
1451
- # # example
1452
- # response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
1453
- # p response.status
1454
- # puts response.body # body is already read in this case
2212
+ # Output:
1455
2213
  #
1456
- # # using block
1457
- # http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
1458
- # p response.status
1459
- # p response['content-type']
1460
- # response.read_body do |str| # read body now
1461
- # print str
1462
- # end
1463
- # }
2214
+ # "{\n \"xyzzy\": \"\",\n \"id\": 201\n}"
1464
2215
  #
1465
2216
  def request_post(path, data, initheader = nil, &block) # :yield: +response+
1466
2217
  request Post.new(path, initheader), data, &block
1467
2218
  end
1468
2219
 
2220
+ # Sends a PUT request to the server;
2221
+ # returns an instance of a subclass of Net::HTTPResponse.
2222
+ #
2223
+ # The request is based on the Net::HTTP::Put object
2224
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
2225
+ #
2226
+ # http = Net::HTTP.new(hostname)
2227
+ # http.put('/todos/1', 'xyzzy')
2228
+ # # => #<Net::HTTPOK 200 OK readbody=true>
2229
+ #
1469
2230
  def request_put(path, data, initheader = nil, &block) #:nodoc:
1470
2231
  request Put.new(path, initheader), data, &block
1471
2232
  end
@@ -1475,16 +2236,25 @@ module Net #:nodoc:
1475
2236
  alias post2 request_post #:nodoc: obsolete
1476
2237
  alias put2 request_put #:nodoc: obsolete
1477
2238
 
1478
-
1479
- # Sends an HTTP request to the HTTP server.
1480
- # Also sends a DATA string if +data+ is given.
2239
+ # Sends an \HTTP request to the server;
2240
+ # returns an instance of a subclass of Net::HTTPResponse.
1481
2241
  #
1482
- # Returns a Net::HTTPResponse object.
2242
+ # The request is based on the Net::HTTPRequest object
2243
+ # created from string +path+, string +data+, and initial headers hash +header+.
2244
+ # That object is an instance of the
2245
+ # {subclass of Net::HTTPRequest}[rdoc-ref:Net::HTTPRequest@Request+Subclasses],
2246
+ # that corresponds to the given uppercase string +name+,
2247
+ # which must be
2248
+ # an {HTTP request method}[https://en.wikipedia.org/wiki/HTTP#Request_methods]
2249
+ # or a {WebDAV request method}[https://en.wikipedia.org/wiki/WebDAV#Implementation].
1483
2250
  #
1484
- # This method never raises Net::* exceptions.
2251
+ # Examples:
1485
2252
  #
1486
- # response = http.send_request('GET', '/index.html')
1487
- # puts response.body
2253
+ # http = Net::HTTP.new(hostname)
2254
+ # http.send_request('GET', '/todos/1')
2255
+ # # => #<Net::HTTPOK 200 OK readbody=true>
2256
+ # http.send_request('POST', '/todos', 'xyzzy')
2257
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
1488
2258
  #
1489
2259
  def send_request(name, path, data = nil, header = nil)
1490
2260
  has_response_body = name != 'HEAD'
@@ -1492,20 +2262,35 @@ module Net #:nodoc:
1492
2262
  request r, data
1493
2263
  end
1494
2264
 
1495
- # Sends an HTTPRequest object +req+ to the HTTP server.
2265
+ # Sends the given request +req+ to the server;
2266
+ # forms the response into a Net::HTTPResponse object.
1496
2267
  #
1497
- # If +req+ is a Net::HTTP::Post or Net::HTTP::Put request containing
1498
- # data, the data is also sent. Providing data for a Net::HTTP::Head or
1499
- # Net::HTTP::Get request results in an ArgumentError.
2268
+ # The given +req+ must be an instance of a
2269
+ # {subclass of Net::HTTPRequest}[rdoc-ref:Net::HTTPRequest@Request+Subclasses].
2270
+ # Argument +body+ should be given only if needed for the request.
1500
2271
  #
1501
- # Returns an HTTPResponse object.
2272
+ # With no block given, returns the response object:
1502
2273
  #
1503
- # When called with a block, passes an HTTPResponse object to the block.
1504
- # The body of the response will not have been read yet;
1505
- # the block can process it using HTTPResponse#read_body,
1506
- # if desired.
2274
+ # http = Net::HTTP.new(hostname)
2275
+ #
2276
+ # req = Net::HTTP::Get.new('/todos/1')
2277
+ # http.request(req)
2278
+ # # => #<Net::HTTPOK 200 OK readbody=true>
2279
+ #
2280
+ # req = Net::HTTP::Post.new('/todos')
2281
+ # http.request(req, 'xyzzy')
2282
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
2283
+ #
2284
+ # With a block given, calls the block with the response and returns the response:
1507
2285
  #
1508
- # This method never raises Net::* exceptions.
2286
+ # req = Net::HTTP::Get.new('/todos/1')
2287
+ # http.request(req) do |res|
2288
+ # p res
2289
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
2290
+ #
2291
+ # Output:
2292
+ #
2293
+ # #<Net::HTTPOK 200 OK readbody=false>
1509
2294
  #
1510
2295
  def request(req, body = nil, &block) # :yield: +response+
1511
2296
  unless started?
@@ -1556,6 +2341,8 @@ module Net #:nodoc:
1556
2341
  begin
1557
2342
  res = HTTPResponse.read_new(@socket)
1558
2343
  res.decode_content = req.decode_content
2344
+ res.body_encoding = @response_body_encoding
2345
+ res.ignore_eof = @ignore_eof
1559
2346
  end while res.kind_of?(HTTPInformation)
1560
2347
 
1561
2348
  res.uri = req.uri
@@ -1575,10 +2362,10 @@ module Net #:nodoc:
1575
2362
  if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method)
1576
2363
  count += 1
1577
2364
  @socket.close if @socket
1578
- D "Conn close because of error #{exception}, and retry"
2365
+ debug "Conn close because of error #{exception}, and retry"
1579
2366
  retry
1580
2367
  end
1581
- D "Conn close because of error #{exception}"
2368
+ debug "Conn close because of error #{exception}"
1582
2369
  @socket.close if @socket
1583
2370
  raise
1584
2371
  end
@@ -1586,7 +2373,7 @@ module Net #:nodoc:
1586
2373
  end_transport req, res
1587
2374
  res
1588
2375
  rescue => exception
1589
- D "Conn close because of error #{exception}"
2376
+ debug "Conn close because of error #{exception}"
1590
2377
  @socket.close if @socket
1591
2378
  raise exception
1592
2379
  end
@@ -1596,11 +2383,11 @@ module Net #:nodoc:
1596
2383
  connect
1597
2384
  elsif @last_communicated
1598
2385
  if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
1599
- D 'Conn close because of keep_alive_timeout'
2386
+ debug 'Conn close because of keep_alive_timeout'
1600
2387
  @socket.close
1601
2388
  connect
1602
2389
  elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
1603
- D "Conn close because of EOF"
2390
+ debug "Conn close because of EOF"
1604
2391
  @socket.close
1605
2392
  connect
1606
2393
  end
@@ -1618,15 +2405,15 @@ module Net #:nodoc:
1618
2405
  @curr_http_version = res.http_version
1619
2406
  @last_communicated = nil
1620
2407
  if @socket.closed?
1621
- D 'Conn socket closed'
2408
+ debug 'Conn socket closed'
1622
2409
  elsif not res.body and @close_on_empty_response
1623
- D 'Conn close'
2410
+ debug 'Conn close'
1624
2411
  @socket.close
1625
2412
  elsif keep_alive?(req, res)
1626
- D 'Conn keep-alive'
2413
+ debug 'Conn keep-alive'
1627
2414
  @last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
1628
2415
  else
1629
- D 'Conn close'
2416
+ debug 'Conn close'
1630
2417
  @socket.close
1631
2418
  end
1632
2419
  end
@@ -1681,11 +2468,14 @@ module Net #:nodoc:
1681
2468
  default_port == port ? addr : "#{addr}:#{port}"
1682
2469
  end
1683
2470
 
1684
- def D(msg)
2471
+ # Adds a message to debugging output
2472
+ def debug(msg)
1685
2473
  return unless @debug_output
1686
2474
  @debug_output << msg
1687
2475
  @debug_output << "\n"
1688
2476
  end
2477
+
2478
+ alias_method :D, :debug
1689
2479
  end
1690
2480
 
1691
2481
  end