32 |
32 |
|
33 |
33 |
# == An HTTP client API for Ruby.
|
34 |
34 |
#
|
35 |
|
# For more details about HTTP, see [RFC2616](http://www.ietf.org/rfc/rfc2616.txt).
|
|
35 |
# Net::HTTP provides a rich library which can be used to build HTTP
|
|
36 |
# user-agents. For more details about HTTP see
|
|
37 |
# [RFC2616](http://www.ietf.org/rfc/rfc2616.txt)
|
36 |
38 |
#
|
37 |
|
# == Examples
|
|
39 |
# Net::HTTP is designed to work closely with URI. URI::HTTP#host,
|
|
40 |
# URI::HTTP#port and URI::HTTP#request_uri are designed to work with
|
|
41 |
# Net::HTTP.
|
38 |
42 |
#
|
39 |
|
# === Fetching Documents
|
|
43 |
# If you are only performing a few GET requests you should try OpenURI.
|
40 |
44 |
#
|
41 |
|
# Simple GET
|
|
45 |
# == How to use Net::HTTP
|
42 |
46 |
#
|
43 |
|
# require 'net/http'
|
44 |
|
# Net::HTTP.get('www.example.com', '/index.html') => String
|
45 |
|
#
|
46 |
|
# Simple GET by URI object
|
47 |
|
#
|
48 |
|
# require 'net/http'
|
49 |
|
# require 'uri'
|
50 |
|
# Net::HTTP.get(URI.parse('http://www.example.com/index.html?count=10')) => String
|
51 |
|
#
|
52 |
|
# More generic GET with dynamic parameters
|
53 |
|
#
|
54 |
|
# require 'net/http'
|
55 |
|
# require 'uri'
|
56 |
|
#
|
57 |
|
# uri = URI.parse('http://www.example.com/index.html')
|
58 |
|
# params = { :limit => 10, :page => 3 }
|
59 |
|
# uri.query = URI.encode_www_form(params)
|
60 |
|
# res = Net::HTTP.get_response(uri)
|
61 |
|
# puts res.body if res.is_a?(Net::HTTPSuccess)
|
62 |
|
#
|
63 |
|
# Even more generic GET with Basic Auth and custom header
|
64 |
|
#
|
65 |
|
# require 'net/http'
|
66 |
|
#
|
67 |
|
# uri = URI.parse('http://www.example.com/index.html?key=value')
|
68 |
|
# req = Net::HTTP::Get.new(uri.request_uri)
|
69 |
|
# req.basic_auth 'user', 'pass'
|
70 |
|
# req['X-Custom-Header'] = Time.now.to_i
|
71 |
|
# res = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
72 |
|
# http.request(req)
|
73 |
|
# }
|
74 |
|
# puts res.body
|
75 |
|
#
|
76 |
|
# Accessing Response data:
|
77 |
|
#
|
78 |
|
# res = Net::HTTP.get_response(URI.parse('http://www.example.com/index.html'))
|
79 |
|
# # Headers
|
80 |
|
# res['Set-Cookie'] => String
|
81 |
|
# res.get_fields('set-cookie') => Array
|
82 |
|
# res.to_hash['set-cookie'] => Array
|
83 |
|
# puts "Headers: #{res.to_hash.inspect}"
|
84 |
|
# # Status
|
85 |
|
# puts res.code => '200'
|
86 |
|
# puts res.message => 'OK'
|
87 |
|
# puts res.class.name => 'HTTPOK'
|
88 |
|
# puts res.body
|
89 |
|
#
|
90 |
|
# === Posting Form Data
|
91 |
|
#
|
92 |
|
# require 'net/http'
|
93 |
|
# require 'uri'
|
94 |
|
#
|
95 |
|
# #1: Simple POST
|
96 |
|
# res = Net::HTTP.post_form(URI.parse('http://www.example.com/search.cgi'),
|
97 |
|
# {'q' => 'ruby', 'max' => '50'})
|
98 |
|
# puts res.body
|
99 |
|
#
|
100 |
|
# #2: POST with basic authentication
|
101 |
|
# res = Net::HTTP.post_form(URI.parse('http://jack:pass@www.example.com/todo.cgi'),
|
102 |
|
# {'from' => '2005-01-01',
|
103 |
|
# 'to' => '2005-03-31'})
|
104 |
|
# puts res.body
|
105 |
|
#
|
106 |
|
# #3: Detailed control
|
107 |
|
# uri = URI.parse('http://www.example.com/todo.cgi')
|
108 |
|
# req = Net::HTTP::Post.new(uri.path)
|
109 |
|
# req.basic_auth 'jack', 'pass'
|
110 |
|
# req.set_form_data({'from' => '2005-01-01', 'to' => '2005-03-31'}, ';')
|
111 |
|
# res = Net::HTTP.new(uri.hostname, uri.port).start {|http| http.request(req) }
|
112 |
|
# case res
|
113 |
|
# when Net::HTTPSuccess, Net::HTTPRedirection
|
114 |
|
# # OK
|
|
47 |
# Net::HTTP provides several convenience methods for performing a GET on a
|
|
48 |
# web server which are described below.
|
|
49 |
#
|
|
50 |
# All examples assume you have loaded Net::HTTP with:
|
|
51 |
#
|
|
52 |
# require 'net/http'
|
|
53 |
#
|
|
54 |
# This will also require 'uri' so you don't need to require it separately.
|
|
55 |
#
|
|
56 |
# The following example code can be used as the basis of a HTTP user-agent
|
|
57 |
# which will perform a variety of request types.
|
|
58 |
#
|
|
59 |
# uri = URI.parse 'http://example.com/some_path?query=string'
|
|
60 |
#
|
|
61 |
# Net::HTTP.start uri.host, uri.port do |http|
|
|
62 |
# request = Net::HTTP::Get.new uri.request_uri
|
|
63 |
#
|
|
64 |
# response = http.request request # Net::HTTPResponse object
|
|
65 |
# end
|
|
66 |
#
|
|
67 |
# Net::HTTP::start immediately creates a connection to an HTTP server which
|
|
68 |
# is kept open for the duration of the block. The connection will remain
|
|
69 |
# open for multiple requests in the block if the server indicates it
|
|
70 |
# supports persistent connections.
|
|
71 |
#
|
|
72 |
# The request types Net::HTTP supports are listed below in the section "HTTP
|
|
73 |
# Request Classes".
|
|
74 |
#
|
|
75 |
# If you wish to re-use a connection across multiple HTTP requests without
|
|
76 |
# automatically closing it you can use ::new instead of ::start. #request
|
|
77 |
# will automatically open a connection to the server if one is not currently
|
|
78 |
# open. You can manually close the connection with #close.
|
|
79 |
#
|
|
80 |
# === Response Data
|
|
81 |
#
|
|
82 |
# uri = URI.parse('http://example.com/index.html')
|
|
83 |
# res = Net::HTTP.get_response(uri)
|
|
84 |
#
|
|
85 |
# # Headers
|
|
86 |
# res['Set-Cookie'] # => String
|
|
87 |
# res.get_fields('set-cookie') # => Array
|
|
88 |
# res.to_hash['set-cookie'] # => Array
|
|
89 |
# puts "Headers: #{res.to_hash.inspect}"
|
|
90 |
#
|
|
91 |
# # Status
|
|
92 |
# puts res.code # => '200'
|
|
93 |
# puts res.message # => 'OK'
|
|
94 |
# puts res.class.name # => 'HTTPOK'
|
|
95 |
#
|
|
96 |
# # Body
|
|
97 |
# puts res.body if res.response_body_permitted?
|
|
98 |
#
|
|
99 |
# === Following Redirection
|
|
100 |
#
|
|
101 |
# Each Net::HTTPResponse object belongs to a class for its response code.
|
|
102 |
#
|
|
103 |
# For example, all 2XX responses are instances of a Net::HTTPSuccess
|
|
104 |
# subclass, a 3XX response is an instance of a Net::HTTPRedirection
|
|
105 |
# subclass and a 200 response is an instance of the Net::HTTPOK class. For
|
|
106 |
# details of response classes, see the section "HTTP Response Classes"
|
|
107 |
# below.
|
|
108 |
#
|
|
109 |
# Using a case statement you can handle various types of responses properly:
|
|
110 |
#
|
|
111 |
# def fetch(uri_str, limit = 10)
|
|
112 |
# # You should choose a better exception.
|
|
113 |
# raise ArgumentError, 'too many HTTP redirects' if limit == 0
|
|
114 |
#
|
|
115 |
# response = Net::HTTP.get_response(URI.parse(uri_str))
|
|
116 |
#
|
|
117 |
# case response
|
|
118 |
# when Net::HTTPSuccess then
|
|
119 |
# response
|
|
120 |
# when Net::HTTPRedirection then
|
|
121 |
# location = response['location']
|
|
122 |
# warn "redirected to #{location}"
|
|
123 |
# fetch(location, limit - 1)
|
115 |
124 |
# else
|
116 |
|
# res.error!
|
|
125 |
# # turns a response object into an error class and raises it
|
|
126 |
# response.error!
|
117 |
127 |
# end
|
|
128 |
# end
|
118 |
129 |
#
|
119 |
|
# #4: Multiple values
|
120 |
|
# res = Net::HTTP.post_form(URI.parse('http://www.example.com/search.cgi'),
|
121 |
|
# {'q' => ['ruby', 'perl'], 'max' => '50'})
|
122 |
|
# puts res.body
|
|
130 |
# print fetch('http://www.ruby-lang.org')
|
123 |
131 |
#
|
124 |
|
# === Accessing via Proxy
|
|
132 |
# === POST
|
125 |
133 |
#
|
126 |
|
# Net::HTTP::Proxy has the same methods as Net::HTTP but its instances always
|
127 |
|
# connect via the proxy, instead of given host.
|
|
134 |
# A POST can be made using the Net::HTTP::Post request class. This example
|
|
135 |
# creates a urlencoded POST body:
|
128 |
136 |
#
|
129 |
|
# require 'net/http'
|
|
137 |
# uri = URI.parse('http://www.example.com/todo.cgi')
|
|
138 |
# req = Net::HTTP::Post.new(uri.path)
|
|
139 |
# req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')
|
130 |
140 |
#
|
131 |
|
# proxy_addr = 'your.proxy.host'
|
132 |
|
# proxy_port = 8080
|
133 |
|
# :
|
134 |
|
# Net::HTTP::Proxy(proxy_addr, proxy_port).start('www.example.com') {|http|
|
135 |
|
# # always connect to your.proxy.addr:8080
|
136 |
|
# :
|
137 |
|
# }
|
138 |
|
#
|
139 |
|
# Since Net::HTTP::Proxy returns Net::HTTP itself when proxy_addr is nil,
|
140 |
|
# there's no need to change code if there's a proxy or not.
|
141 |
|
#
|
142 |
|
# There are two additional parameters in Net::HTTP::Proxy which you can use to
|
143 |
|
# specify a proxy username and password:
|
144 |
|
#
|
145 |
|
# Net::HTTP::Proxy(proxy_addr, proxy_port, proxy_user = nil, proxy_pass = nil)
|
146 |
|
#
|
147 |
|
# You may use them to work with authorization-enabled proxies:
|
148 |
|
#
|
149 |
|
# require 'net/http'
|
150 |
|
# require 'uri'
|
151 |
|
#
|
152 |
|
# proxy_host = 'your.proxy.host'
|
153 |
|
# proxy_port = 8080
|
154 |
|
# uri = URI.parse(ENV['http_proxy'])
|
155 |
|
# proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
|
156 |
|
# Net::HTTP::Proxy(proxy_host, proxy_port,
|
157 |
|
# proxy_user, proxy_pass).start('www.example.com') {|http|
|
158 |
|
# # always connect to your.proxy.addr:8080 using specified username and password
|
159 |
|
# :
|
160 |
|
# }
|
|
141 |
# res = Net::HTTP.new(uri.hostname, uri.port).start do |http|
|
|
142 |
# http.request(req)
|
|
143 |
# end
|
161 |
144 |
#
|
162 |
|
# Note that net/http does not use the HTTP_PROXY environment variable.
|
163 |
|
# If you want to use a proxy, you must set it explicitly.
|
|
145 |
# case res
|
|
146 |
# when Net::HTTPSuccess, Net::HTTPRedirection
|
|
147 |
# # OK
|
|
148 |
# else
|
|
149 |
# res.error!
|
|
150 |
# end
|
164 |
151 |
#
|
165 |
|
# === Following Redirection
|
|
152 |
# At this time Net::HTTP does not support multipart/form-data. To send
|
|
153 |
# multipart/form-data use Net::HTTPRequest#body= and
|
|
154 |
# Net::HTTPRequest#content_type=:
|
|
155 |
#
|
|
156 |
# req = Net::HTTP::Post.new(uri.path)
|
|
157 |
# req.body = multipart_data
|
|
158 |
# req.content_type = 'multipart/form-data'
|
|
159 |
#
|
|
160 |
# Other requests that can contain a body such as PUT can be created in the
|
|
161 |
# same way using the corresponding request class (Net::HTTP::Put).
|
|
162 |
#
|
|
163 |
# === Setting Headers
|
|
164 |
#
|
|
165 |
# The following example performs a conditional GET using the
|
|
166 |
# If-Modified-Since header. If the files has not been modified since the
|
|
167 |
# time in the header a Not Modified response will be returned. See RFC 2616
|
|
168 |
# section 9.3 for further details.
|
|
169 |
#
|
|
170 |
# uri = URI.parse('http://example.com/cached_response')
|
|
171 |
# file = File.stat 'cached_response'
|
|
172 |
#
|
|
173 |
# req = Net::HTTP::Get.new(uri.request_uri)
|
|
174 |
# req['If-Modified-Since'] = file.mtime.rfc2822
|
|
175 |
#
|
|
176 |
# res = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
|
177 |
# http.request(req)
|
|
178 |
# }
|
|
179 |
#
|
|
180 |
# open 'cached_response', 'w' do |io|
|
|
181 |
# io.write res.body
|
|
182 |
# end if res.is_a?(Net::HTTPSuccess)
|
|
183 |
#
|
|
184 |
# === Basic Authentication
|
|
185 |
#
|
|
186 |
# Basic authentication is performed according to
|
|
187 |
# [RFC2617](http://www.ietf.org/rfc/rfc2617.txt)
|
|
188 |
#
|
|
189 |
# uri = URI.parse('http://example.com/index.html?key=value')
|
|
190 |
#
|
|
191 |
# req = Net::HTTP::Get.new(uri.request_uri)
|
|
192 |
# req.basic_auth 'user', 'pass'
|
|
193 |
#
|
|
194 |
# res = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
|
195 |
# http.request(req)
|
|
196 |
# }
|
|
197 |
# puts res.body
|
|
198 |
#
|
|
199 |
# === Streaming Response Bodies
|
|
200 |
#
|
|
201 |
# By default Net::HTTP reads an entire response into memory. If you are
|
|
202 |
# handling large files or wish to implement a progress bar you can instead
|
|
203 |
# stream the body directly to an IO.
|
166 |
204 |
#
|
167 |
|
# require 'net/http'
|
168 |
|
# require 'uri'
|
|
205 |
# uri = URI.parse 'http://example.com/large_file'
|
169 |
206 |
#
|
170 |
|
# def fetch(uri_str, limit = 10)
|
171 |
|
# # You should choose better exception.
|
172 |
|
# raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
173 |
|
#
|
174 |
|
# response = Net::HTTP.get_response(URI.parse(uri_str))
|
175 |
|
# case response
|
176 |
|
# when Net::HTTPSuccess then response
|
177 |
|
# when Net::HTTPRedirection then fetch(response['location'], limit - 1)
|
178 |
|
# else
|
179 |
|
# response.error!
|
|
207 |
# Net::HTTP.start uri.host, uri.port do |http|
|
|
208 |
# request = Net::HTTP::Get.new uri.request_uri
|
|
209 |
#
|
|
210 |
# http.request request do |response|
|
|
211 |
# open 'large_file', 'w' do |io|
|
|
212 |
# response.read_body do |chunk|
|
|
213 |
# io.write chunk
|
|
214 |
# end
|
180 |
215 |
# end
|
181 |
216 |
# end
|
|
217 |
# end
|
|
218 |
#
|
|
219 |
# === HTTPS
|
|
220 |
#
|
|
221 |
# HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=.
|
|
222 |
#
|
|
223 |
# uri = URI.parse 'https://secure.example.com/some_path?query=string'
|
|
224 |
#
|
|
225 |
# Net::HTTP.new uri.host, uri.port
|
|
226 |
# http.use_ssl = uri.scheme == 'https'
|
|
227 |
#
|
|
228 |
# http.start do
|
|
229 |
# request = Net::HTTP::Get.new uri.request_uri
|
|
230 |
#
|
|
231 |
# response = http.request request # Net::HTTPResponse object
|
|
232 |
# end
|
|
233 |
#
|
|
234 |
# In previous versions of ruby you would need to require 'net/https' to use
|
|
235 |
# HTTPS. This is no longer true.
|
|
236 |
#
|
|
237 |
# === Proxies
|
182 |
238 |
#
|
183 |
|
# print fetch('http://www.ruby-lang.org')
|
|
239 |
# Net::HTTP::Proxy has the same methods as Net::HTTP but its instances always
|
|
240 |
# connect via the proxy, instead of given host.
|
|
241 |
#
|
|
242 |
# proxy_addr = 'your.proxy.host'
|
|
243 |
# proxy_port = 8080
|
184 |
244 |
#
|
185 |
|
# Net::HTTPSuccess and Net::HTTPRedirection are HTTPResponse subclasses.
|
186 |
|
# All HTTPResponse objects belong to their own response class which
|
187 |
|
# indicates the HTTP result status.
|
188 |
|
#
|
189 |
|
# === HTTP Request Classes
|
190 |
|
#
|
191 |
|
# Here is HTTP request class hierarchy.
|
192 |
|
#
|
193 |
|
# Net::HTTPRequest
|
194 |
|
# Net::HTTP::Get
|
195 |
|
# Net::HTTP::Head
|
196 |
|
# Net::HTTP::Post
|
197 |
|
# Net::HTTP::Put
|
198 |
|
# Net::HTTP::Proppatch
|
199 |
|
# Net::HTTP::Lock
|
200 |
|
# Net::HTTP::Unlock
|
201 |
|
# Net::HTTP::Options
|
202 |
|
# Net::HTTP::Propfind
|
203 |
|
# Net::HTTP::Delete
|
204 |
|
# Net::HTTP::Move
|
205 |
|
# Net::HTTP::Copy
|
206 |
|
# Net::HTTP::Mkcol
|
207 |
|
# Net::HTTP::Trace
|
208 |
|
#
|
209 |
|
# === HTTP Response Classes
|
210 |
|
#
|
211 |
|
# Here is HTTP response class hierarchy.
|
212 |
|
# All classes are defined in Net module.
|
213 |
|
#
|
214 |
|
# HTTPResponse
|
215 |
|
# HTTPUnknownResponse
|
216 |
|
# HTTPInformation # 1xx
|
217 |
|
# HTTPContinue # 100
|
218 |
|
# HTTPSwitchProtocol # 101
|
219 |
|
# HTTPSuccess # 2xx
|
220 |
|
# HTTPOK # 200
|
221 |
|
# HTTPCreated # 201
|
222 |
|
# HTTPAccepted # 202
|
223 |
|
# HTTPNonAuthoritativeInformation # 203
|
224 |
|
# HTTPNoContent # 204
|
225 |
|
# HTTPResetContent # 205
|
226 |
|
# HTTPPartialContent # 206
|
227 |
|
# HTTPRedirection # 3xx
|
228 |
|
# HTTPMultipleChoice # 300
|
229 |
|
# HTTPMovedPermanently # 301
|
230 |
|
# HTTPFound # 302
|
231 |
|
# HTTPSeeOther # 303
|
232 |
|
# HTTPNotModified # 304
|
233 |
|
# HTTPUseProxy # 305
|
234 |
|
# HTTPTemporaryRedirect # 307
|
235 |
|
# HTTPClientError # 4xx
|
236 |
|
# HTTPBadRequest # 400
|
237 |
|
# HTTPUnauthorized # 401
|
238 |
|
# HTTPPaymentRequired # 402
|
239 |
|
# HTTPForbidden # 403
|
240 |
|
# HTTPNotFound # 404
|
241 |
|
# HTTPMethodNotAllowed # 405
|
242 |
|
# HTTPNotAcceptable # 406
|
243 |
|
# HTTPProxyAuthenticationRequired # 407
|
244 |
|
# HTTPRequestTimeOut # 408
|
245 |
|
# HTTPConflict # 409
|
246 |
|
# HTTPGone # 410
|
247 |
|
# HTTPLengthRequired # 411
|
248 |
|
# HTTPPreconditionFailed # 412
|
249 |
|
# HTTPRequestEntityTooLarge # 413
|
250 |
|
# HTTPRequestURITooLong # 414
|
251 |
|
# HTTPUnsupportedMediaType # 415
|
252 |
|
# HTTPRequestedRangeNotSatisfiable # 416
|
253 |
|
# HTTPExpectationFailed # 417
|
254 |
|
# HTTPServerError # 5xx
|
255 |
|
# HTTPInternalServerError # 500
|
256 |
|
# HTTPNotImplemented # 501
|
257 |
|
# HTTPBadGateway # 502
|
258 |
|
# HTTPServiceUnavailable # 503
|
259 |
|
# HTTPGatewayTimeOut # 504
|
260 |
|
# HTTPVersionNotSupported # 505
|
|
245 |
# Net::HTTP::Proxy(proxy_addr, proxy_port).start('www.example.com') {|http|
|
|
246 |
# # always connect to your.proxy.addr:8080
|
|
247 |
# }
|
|
248 |
#
|
|
249 |
# Net::HTTP::Proxy returns a Net::HTTP instance when proxy_addr is nil so
|
|
250 |
# there is no need for conditional code.
|
|
251 |
#
|
|
252 |
# See Net::HTTP::Proxy for further details and examples such as proxies that
|
|
253 |
# require a username and password.
|
|
254 |
#
|
|
255 |
# == Simple Examples
|
|
256 |
#
|
|
257 |
# The Net::HTTP methods in the following examples do not persist
|
|
258 |
# connections. They are not recommended if you are performing many HTTP
|
|
259 |
# requests.
|
|
260 |
#
|
|
261 |
# === GET
|
|
262 |
#
|
|
263 |
# Net::HTTP.get('example.com', '/index.html') # => String
|
|
264 |
#
|
|
265 |
# === GET by URI
|
|
266 |
#
|
|
267 |
# uri = URI.parse('http://example.com/index.html?count=10')
|
|
268 |
# Net::HTTP.get(uri) # => String
|
|
269 |
#
|
|
270 |
# === GET with Dynamic Parameters
|
|
271 |
#
|
|
272 |
# uri = URI.parse('http://example.com/index.html')
|
|
273 |
# params = { :limit => 10, :page => 3 }
|
|
274 |
# uri.query = URI.encode_www_form(params)
|
|
275 |
#
|
|
276 |
# res = Net::HTTP.get_response(uri)
|
|
277 |
# puts res.body if res.is_a?(Net::HTTPSuccess)
|
|
278 |
#
|
|
279 |
# === POST
|
|
280 |
#
|
|
281 |
# uri = URI.parse('http://www.example.com/search.cgi')
|
|
282 |
# res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
|
|
283 |
# puts res.body
|
|
284 |
#
|
|
285 |
# === POST with Multiple Values
|
|
286 |
#
|
|
287 |
# uri = URI.parse('http://www.example.com/search.cgi')
|
|
288 |
# res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
|
|
289 |
# puts res.body
|
|
290 |
#
|
|
291 |
# == HTTP Request Classes
|
|
292 |
#
|
|
293 |
# Here is the HTTP request class hierarchy.
|
|
294 |
#
|
|
295 |
# * Net::HTTPRequest
|
|
296 |
# * Net::HTTP::Get
|
|
297 |
# * Net::HTTP::Head
|
|
298 |
# * Net::HTTP::Post
|
|
299 |
# * Net::HTTP::Put
|
|
300 |
# * Net::HTTP::Proppatch
|
|
301 |
# * Net::HTTP::Lock
|
|
302 |
# * Net::HTTP::Unlock
|
|
303 |
# * Net::HTTP::Options
|
|
304 |
# * Net::HTTP::Propfind
|
|
305 |
# * Net::HTTP::Delete
|
|
306 |
# * Net::HTTP::Move
|
|
307 |
# * Net::HTTP::Copy
|
|
308 |
# * Net::HTTP::Mkcol
|
|
309 |
# * Net::HTTP::Trace
|
|
310 |
#
|
|
311 |
# == HTTP Response Classes
|
|
312 |
#
|
|
313 |
# Here is HTTP response class hierarchy. All classes are defined in Net
|
|
314 |
# module and are subclasses of Net::HTTPResponse.
|
|
315 |
#
|
|
316 |
# HTTPUnknownResponse:: For unhandled HTTP extenensions
|
|
317 |
# HTTPInformation:: 1xx
|
|
318 |
# HTTPContinue:: 100
|
|
319 |
# HTTPSwitchProtocol:: 101
|
|
320 |
# HTTPSuccess:: 2xx
|
|
321 |
# HTTPOK:: 200
|
|
322 |
# HTTPCreated:: 201
|
|
323 |
# HTTPAccepted:: 202
|
|
324 |
# HTTPNonAuthoritativeInformation:: 203
|
|
325 |
# HTTPNoContent:: 204
|
|
326 |
# HTTPResetContent:: 205
|
|
327 |
# HTTPPartialContent:: 206
|
|
328 |
# HTTPRedirection:: 3xx
|
|
329 |
# HTTPMultipleChoice:: 300
|
|
330 |
# HTTPMovedPermanently:: 301
|
|
331 |
# HTTPFound:: 302
|
|
332 |
# HTTPSeeOther:: 303
|
|
333 |
# HTTPNotModified:: 304
|
|
334 |
# HTTPUseProxy:: 305
|
|
335 |
# HTTPTemporaryRedirect:: 307
|
|
336 |
# HTTPClientError:: 4xx
|
|
337 |
# HTTPBadRequest:: 400
|
|
338 |
# HTTPUnauthorized:: 401
|
|
339 |
# HTTPPaymentRequired:: 402
|
|
340 |
# HTTPForbidden:: 403
|
|
341 |
# HTTPNotFound:: 404
|
|
342 |
# HTTPMethodNotAllowed:: 405
|
|
343 |
# HTTPNotAcceptable:: 406
|
|
344 |
# HTTPProxyAuthenticationRequired:: 407
|
|
345 |
# HTTPRequestTimeOut:: 408
|
|
346 |
# HTTPConflict:: 409
|
|
347 |
# HTTPGone:: 410
|
|
348 |
# HTTPLengthRequired:: 411
|
|
349 |
# HTTPPreconditionFailed:: 412
|
|
350 |
# HTTPRequestEntityTooLarge:: 413
|
|
351 |
# HTTPRequestURITooLong:: 414
|
|
352 |
# HTTPUnsupportedMediaType:: 415
|
|
353 |
# HTTPRequestedRangeNotSatisfiable:: 416
|
|
354 |
# HTTPExpectationFailed:: 417
|
|
355 |
# HTTPServerError:: 5xx
|
|
356 |
# HTTPInternalServerError:: 500
|
|
357 |
# HTTPNotImplemented:: 501
|
|
358 |
# HTTPBadGateway:: 502
|
|
359 |
# HTTPServiceUnavailable:: 503
|
|
360 |
# HTTPGatewayTimeOut:: 504
|
|
361 |
# HTTPVersionNotSupported:: 505
|
|
362 |
#
|
|
363 |
# There is also the Net::HTTPBadResponse exception which is raised when
|
|
364 |
# there is a protocol error.
|
261 |
365 |
#
|
262 |
366 |
# == Switching Net::HTTP versions
|
263 |
367 |
#
|
264 |
|
# You can use net/http.rb 1.1 features (bundled with Ruby 1.6)
|
265 |
|
# by calling HTTP.version_1_1. Calling Net::HTTP.version_1_2
|
266 |
|
# allows you to use 1.2 features again.
|
|
368 |
# You can use net/http.rb 1.1 features (bundled with Ruby 1.6) by calling
|
|
369 |
# HTTP.version_1_1. Calling Net::HTTP.version_1_2 allows you to use 1.2
|
|
370 |
# features again. Do not confuse this with HTTP protocol features.
|
267 |
371 |
#
|
268 |
|
# # example
|
269 |
|
# Net::HTTP.start {|http1| ...(http1 has 1.2 features)... }
|
|
372 |
# # example
|
|
373 |
# Net::HTTP.start {|http1| ...(http1 has 1.2 features)... }
|
270 |
374 |
#
|
271 |
|
# Net::HTTP.version_1_1
|
272 |
|
# Net::HTTP.start {|http2| ...(http2 has 1.1 features)... }
|
|
375 |
# Net::HTTP.version_1_1
|
|
376 |
# Net::HTTP.start {|http2| ...(http2 has 1.1 features)... }
|
273 |
377 |
#
|
274 |
|
# Net::HTTP.version_1_2
|
275 |
|
# Net::HTTP.start {|http3| ...(http3 has 1.2 features)... }
|
|
378 |
# Net::HTTP.version_1_2
|
|
379 |
# Net::HTTP.start {|http3| ...(http3 has 1.2 features)... }
|
276 |
380 |
#
|
277 |
381 |
# Switching versions is NOT thread-safe.
|
278 |
382 |
#
|
... | ... | |
573 |
677 |
|
574 |
678 |
attr_accessor :close_on_empty_response
|
575 |
679 |
|
576 |
|
# returns true if use SSL/TLS with HTTP.
|
|
680 |
# returns true if this session will use SSL or TLS.
|
577 |
681 |
def use_ssl?
|
578 |
682 |
@use_ssl
|
579 |
683 |
end
|
580 |
684 |
|
581 |
685 |
# Turn on/off SSL.
|
582 |
|
# This flag must be set before starting session.
|
583 |
|
# If you change use_ssl value after session started,
|
584 |
|
# a Net::HTTP object raises IOError.
|
|
686 |
#
|
|
687 |
# This flag must be set before starting a session. If you change use_ssl
|
|
688 |
# value after session started, a Net::HTTP object raises IOError.
|
585 |
689 |
def use_ssl=(flag)
|
586 |
690 |
flag = (flag ? true : false)
|
587 |
691 |
if started? and @use_ssl != flag
|
... | ... | |
594 |
698 |
ssl_version key cert ca_file ca_path cert_store ciphers
|
595 |
699 |
verify_mode verify_callback verify_depth ssl_timeout
|
596 |
700 |
)
|
597 |
|
attr_accessor(*SSL_ATTRIBUTES)
|
598 |
701 |
|
599 |
|
# return the X.509 certificates the server presented.
|
|
702 |
# Sets path of a CA certification file in PEM format.
|
|
703 |
#
|
|
704 |
# The file can contain several CA certificates.
|
|
705 |
attr_accessor :ca_file
|
|
706 |
|
|
707 |
# Sets path of a CA certification directory containing certifications in
|
|
708 |
# PEM format.
|
|
709 |
attr_accessor :ca_path
|
|
710 |
|
|
711 |
# Sets an OpenSSL::X509::Certificate object as client certificate.
|
|
712 |
# (This method is appeared in Michal Rokos's OpenSSL extension).
|
|
713 |
attr_accessor :cert
|
|
714 |
|
|
715 |
# Sets the X509::Store to verify peer certificate.
|
|
716 |
attr_accessor :cert_store
|
|
717 |
|
|
718 |
# Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers=
|
|
719 |
attr_accessor :ciphers
|
|
720 |
|
|
721 |
# Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
|
|
722 |
# (This method is appeared in Michal Rokos's OpenSSL extension.)
|
|
723 |
attr_accessor :key
|
|
724 |
|
|
725 |
# Sets the SSL timeout seconds.
|
|
726 |
attr_accessor :ssl_timeout
|
|
727 |
|
|
728 |
# Sets the SSL version. See OpenSSL::SSL::SSLContext#ssl_version=
|
|
729 |
attr_accessor :ssl_version
|
|
730 |
|
|
731 |
# Sets the verify callback for the server certification verification.
|
|
732 |
attr_accessor :verify_callback
|
|
733 |
|
|
734 |
# Sets the maximum depth for the certificate chain verification.
|
|
735 |
attr_accessor :verify_depth
|
|
736 |
|
|
737 |
# Sets the flags for server the certification verification at beginning of
|
|
738 |
# SSL/TLS session.
|
|
739 |
#
|
|
740 |
# OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable.
|
|
741 |
attr_accessor :verify_mode
|
|
742 |
|
|
743 |
# Returns the X.509 certificates the server presented.
|
600 |
744 |
def peer_cert
|
601 |
745 |
if not use_ssl? or not @socket
|
602 |
746 |
return nil
|
... | ... | |
709 |
853 |
@proxy_pass = nil
|
710 |
854 |
|
711 |
855 |
# Creates an HTTP proxy class.
|
|
856 |
#
|
712 |
857 |
# Arguments are address/port of proxy host and username/password
|
713 |
|
# if authorization on proxy server is required.
|
|
858 |
# if authorization on proxy server is required. The proxy will use the
|
|
859 |
# #default_port if no proxy port is provided.
|
|
860 |
#
|
714 |
861 |
# You can replace the HTTP class with created proxy class.
|
715 |
862 |
#
|
716 |
863 |
# If ADDRESS is nil, this method returns self (Net::HTTP).
|
717 |
864 |
#
|
718 |
|
# # Example
|
719 |
|
# proxy_class = Net::HTTP::Proxy('proxy.example.com', 8080)
|
720 |
|
# :
|
721 |
|
# proxy_class.start('www.ruby-lang.org') {|http|
|
722 |
|
# # connecting proxy.foo.org:8080
|
723 |
|
# :
|
724 |
|
# }
|
|
865 |
# # Example
|
|
866 |
# proxy_class = Net::HTTP::Proxy('proxy.example.com', 8080)
|
|
867 |
#
|
|
868 |
# proxy_class.start('www.ruby-lang.org') {|http|
|
|
869 |
# # connecting proxy.foo.org:8080
|
|
870 |
# }
|
|
871 |
#
|
|
872 |
# You may use them to work with authorization-enabled proxies:
|
|
873 |
#
|
|
874 |
# proxy_host = 'your.proxy.example'
|
|
875 |
# proxy_port = 8080
|
|
876 |
# uri = URI.parse(ENV['HTTP_PROXY'])
|
|
877 |
# proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
|
|
878 |
#
|
|
879 |
# proxy = Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass)
|
|
880 |
# proxy.start('www.example.com') { |http|
|
|
881 |
# # always connect to your.proxy.example:8080 using specified username
|
|
882 |
# # and password
|
|
883 |
# }
|
|
884 |
#
|
|
885 |
# Note that net/http does not use the HTTP_PROXY environment variable.
|
|
886 |
# If you want to use a proxy, you must set it explicitly.
|
725 |
887 |
#
|
726 |
888 |
def HTTP.Proxy(p_addr, p_port = nil, p_user = nil, p_pass = nil)
|
727 |
889 |
return self unless p_addr
|
... | ... | |
1583 |
1745 |
|
1584 |
1746 |
alias content_type= set_content_type
|
1585 |
1747 |
|
1586 |
|
# Set header fields and a body from HTML form data.
|
1587 |
|
# +params+ should be a Hash containing HTML form data.
|
1588 |
|
# Optional argument +sep+ means data record separator.
|
|
1748 |
# Set header fields and a body from HTML form data. +params+ should be a
|
|
1749 |
# Hash containing HTML form data. Optional argument +sep+ means data
|
|
1750 |
# record separator.
|
1589 |
1751 |
#
|
1590 |
1752 |
# This method also set Content-Type: header field to
|
1591 |
1753 |
# application/x-www-form-urlencoded.
|
... | ... | |
1987 |
2149 |
# xxx HTTPUnknownResponse
|
1988 |
2150 |
#
|
1989 |
2151 |
class HTTPResponse
|
1990 |
|
# true if the response has body.
|
|
2152 |
# true if the response has a body.
|
1991 |
2153 |
def HTTPResponse.body_permitted?
|
1992 |
2154 |
self::HAS_BODY
|
1993 |
2155 |
end
|
... | ... | |
2307 |
2469 |
self.class
|
2308 |
2470 |
end
|
2309 |
2471 |
|
2310 |
|
def error! #:nodoc:
|
|
2472 |
# raises this HTTPResponse as its matching exception type. Note that you
|
|
2473 |
# may not raise an HTTPSuccess response subclass.
|
|
2474 |
def error!
|
2311 |
2475 |
raise error_type().new(@code + ' ' + @message.dump, self)
|
2312 |
2476 |
end
|
2313 |
2477 |
|