Object
The HTTPClient class provides several methods for accessing Web resources via HTTP.
HTTPClient instance is designed to be MT-safe. You can call a HTTPClient instance from several threads without synchronization after setting up an instance.
clnt = HTTPClient.new
clnt.set_cookie_store('/home/nahi/cookie.dat')
urls.each do |url|
Thread.new(url) do |u|
p clnt.head(u).status
end
end
At first, how to create your client. See initialize for more detail.
Create simple client.
clnt = HTTPClient.new
Accessing resources through HTTP proxy. You can use environment variable ‘http_proxy’ or ‘HTTP_PROXY’ instead.
clnt = HTTPClient.new('http://myproxy:8080')
See get_content.
Get content of specified URL. It returns a String of whole result.
puts clnt.get_content('http://dev.ctor.org/')
Get content as chunks of String. It yields chunks of String.
clnt.get_content('http://dev.ctor.org/') do |chunk|
puts chunk
end
See head, get, post, put, delete, options, propfind, proppatch and trace. It returns a HTTP::Message instance as a response.
Do HEAD request.
res = clnt.head(uri) p res.header['Last-Modified'][0]
Do GET request with query.
query = { 'keyword' => 'ruby', 'lang' => 'en' }
res = clnt.get(uri, query)
p res.status
p res.contenttype
p res.header['X-Custom']
puts res.content
See post.
Do POST a form data.
body = { 'keyword' => 'ruby', 'lang' => 'en' }
res = clnt.post(uri, body)
Do multipart file upload with POST. No need to set extra header by yourself from httpclient/2.1.4.
File.open('/tmp/post_data') do |file|
body = { 'upload' => file, 'user' => 'nahi' }
res = clnt.post(uri, body)
end
Ruby needs to be compiled with OpenSSL.
Get content of specified URL via SSL. Just pass an URL which starts with ‘https://’.
https_url = 'https://www.rsa.com' clnt.get_content(https_url)
Getting peer certificate from response.
res = clnt.get(https_url) p res.peer_cert #=> returns OpenSSL::X509::Certificate
Configuring OpenSSL options. See HTTPClient::SSLConfig for more details.
user_cert_file = 'cert.pem' user_key_file = 'privkey.pem' clnt.ssl_config.set_client_cert_file(user_cert_file, user_key_file) clnt.get_content(https_url)
Using volatile Cookies. Nothing to do. HTTPClient handles Cookies.
clnt = HTTPClient.new clnt.get_content(url1) # receives Cookies. clnt.get_content(url2) # sends Cookies if needed.
Saving non volatile Cookies to a specified file. Need to set a file at first and invoke save method at last.
clnt = HTTPClient.new
clnt.set_cookie_store('/home/nahi/cookie.dat')
clnt.get_content(url)
...
clnt.save_cookie_store
Disabling Cookies.
clnt = HTTPClient.new clnt.cookie_manager = nil
Authentication with Web server. Supports BasicAuth, DigestAuth, and Negotiate/NTLM (requires ruby/ntlm module).
clnt = HTTPClient.new
domain = 'http://dev.ctor.org/http-access2/'
user = 'user'
password = 'user'
clnt.set_auth(domain, user, password)
p clnt.get_content('http://dev.ctor.org/http-access2/login').status
Authentication with Proxy server. Supports BasicAuth and NTLM (requires win32/sspi)
clnt = HTTPClient.new(proxy) user = 'proxy' password = 'proxy' clnt.set_proxy_auth(user, password) p clnt.get_content(url)
Pass a Hash or an Array for extheader argument.
extheader = { 'Accept' => '*/*' }
clnt.get_content(uri, query, extheader)
extheader = [['Accept', 'image/jpeg'], ['Accept', 'image/png']]
clnt.get_content(uri, query, extheader)
See head_async, get_async, post_async, put_async, delete_async, options_async, propfind_async, proppatch_async, and trace_async. It immediately returns a HTTPClient::Connection instance as a returning value.
connection = clnt.post_async(url, body)
print 'posting.'
while true
break if connection.finished?
print '.'
sleep 1
end
puts '.'
res = connection.pop
p res.status
p res.content.read # res.content is an IO for the res of async method.
You can invoke get_content, get, etc. without creating HTTPClient instance.
ruby -rhttpclient -e 'puts HTTPClient.get_content(ARGV.shift)' http://dev.ctor.org/ ruby -rhttpclient -e 'p HTTPClient.head(ARGV.shift).header["last-modified"]' http://dev.ctor.org/
HTTPClient - HTTP
client library. Copyright (C) 2000-2009 NAKAMURA, Hiroshi
This program is copyrighted free software by NAKAMURA, Hiroshi. You can redistribute it and/or modify it under the same terms of Ruby’s license; either the dual license version in 2003, or any later version.
HTTPClient - HTTP
client library. Copyright (C) 2000-2009 NAKAMURA, Hiroshi
This program is copyrighted free software by NAKAMURA, Hiroshi. You can redistribute it and/or modify it under the same terms of Ruby’s license; either the dual license version in 2003, or any later version.
Default extheader for PROPFIND request.
An array of request filter which can trap HTTP request/response. See HTTPClient::WWWAuth to see how to use it.
How many times get_content and post_content follows HTTP redirect. 10 by default.
Creates a HTTPClient instance which manages sessions, cookies, etc.
HTTPClient.new takes 3 optional arguments for proxy url string, User-Agent String and From header String. User-Agent and From are embedded in HTTP request Header if given. No User-Agent and From header added without setting it explicitly.
proxy = 'http://myproxy:8080' agent_name = 'MyAgent/0.1' from = 'from@example.com' HTTPClient.new(proxy, agent_name, from)
You can use a keyword argument style Hash. Keys are :proxy, :agent_name and :from.
HTTPClient.new(:agent_name = 'MyAgent/0.1')
# File lib/httpclient.rb, line 340
340: def initialize(*args)
341: proxy, agent_name, from = keyword_argument(args, :proxy, :agent_name, :from)
342: @proxy = nil # assigned later.
343: @no_proxy = nil
344: @www_auth = WWWAuth.new
345: @proxy_auth = ProxyAuth.new
346: @request_filter = [@proxy_auth, @www_auth]
347: @debug_dev = nil
348: @redirect_uri_callback = method(:default_redirect_uri_callback)
349: @test_loopback_response = []
350: @session_manager = SessionManager.new(self)
351: @session_manager.agent_name = agent_name
352: @session_manager.from = from
353: @session_manager.ssl_config = @ssl_config = SSLConfig.new(self)
354: @cookie_manager = WebAgent::CookieManager.new
355: @follow_redirect_count = 10
356: load_environment
357: self.proxy = proxy if proxy
358: end
# File lib/httpclient.rb, line 266
266: def attr_proxy(symbol, assignable = false)
267: name = symbol.to_s
268: define_method(name) {
269: @session_manager.__send__(name)
270: }
271: if assignable
272: aname = name + '='
273: define_method(aname) { |rhs|
274: reset_all
275: @session_manager.__send__(aname, rhs)
276: }
277: end
278: end
Returns debug device if exists. See debug_dev=.
# File lib/httpclient.rb, line 361
361: def debug_dev
362: @debug_dev
363: end
Sets debug device. Once debug device is set, all HTTP requests and responses are dumped to given device. dev must respond to << for dump.
Calling this method resets all existing sessions.
# File lib/httpclient.rb, line 369
369: def debug_dev=(dev)
370: @debug_dev = dev
371: reset_all
372: @session_manager.debug_dev = dev
373: end
A default method for redirect uri callback. This method is used by HTTPClient instance by default. This callback allows relative redirect such as
Location: ../foo/
in HTTP header.
# File lib/httpclient.rb, line 570
570: def default_redirect_uri_callback(uri, res)
571: newuri = URI.parse(res.header['location'][0])
572: if https?(uri) && !https?(newuri)
573: raise BadResponseError.new("redirecting to non-https resource")
574: end
575: unless newuri.is_a?(URI::HTTP)
576: newuri = uri + newuri
577: STDERR.puts("could be a relative URI in location header which is not recommended")
578: STDERR.puts("'The field value consists of a single absolute URI' in HTTP spec")
579: end
580: puts "redirect to: #{newuri}" if $DEBUG
581: newuri
582: end
Sends DELETE request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 605
605: def delete(uri, extheader = {}, &block)
606: request(:delete, uri, nil, nil, extheader, &block)
607: end
Sends DELETE request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 695
695: def delete_async(uri, extheader = {})
696: request_async(:delete, uri, nil, nil, extheader)
697: end
Sends GET request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 590
590: def get(uri, query = nil, extheader = {}, &block)
591: request(:get, uri, query, nil, extheader, &block)
592: end
Sends GET request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 677
677: def get_async(uri, query = nil, extheader = {})
678: request_async(:get, uri, query, nil, extheader)
679: end
Retrieves a web resource.
| uri | a String or an URI object which represents an URL of web resource. |
| query | a Hash or an Array of query part of URL. e.g. { “a” => “b” } => ‘host/part?a=b’. Give an array to pass multiple value like
|
| extheader | a Hash or an Array of extra headers. e.g. { ‘Accept’ => ‘/’ } or [[‘Accept’, ‘image/jpeg’], [‘Accept’, ‘image/png’]]. |
| &block | Give a block to get chunked message-body of response like get_content(uri) { |chunked_body| … }. Size of each chunk may not be the same. |
get_content follows HTTP redirect status (see HTTP::Status.redirect?) internally and try to retrieve content from redirected URL. See redirect_uri_callback= how HTTP redirection is handled.
If you need to get full HTTP response including HTTP status and headers, use get method. get returns HTTP::Message as a response and you need to follow HTTP redirect by yourself if you need.
# File lib/httpclient.rb, line 518
518: def get_content(uri, query = nil, extheader = {}, &block)
519: follow_redirect(:get, uri, query, nil, extheader, &block).content
520: end
Sends HEAD request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 585
585: def head(uri, query = nil, extheader = {})
586: request(:head, uri, query, nil, extheader)
587: end
Sends HEAD request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 671
671: def head_async(uri, query = nil, extheader = {})
672: request_async(:head, uri, query, nil, extheader)
673: end
Returns NO_PROXY setting String if given.
# File lib/httpclient.rb, line 411
411: def no_proxy
412: @no_proxy
413: end
Sets NO_PROXY setting String. no_proxy must be a comma separated String. Each entry must be ‘host’ or ‘host:port’ such as; HTTPClient#no_proxy = ‘example.com,example.co.jp:443’
‘localhost’ is treated as a no_proxy site regardless of explicitly listed. HTTPClient checks given URI objects before accessing it. ‘host’ is tail string match. No IP-addr conversion.
You can use environment variable ‘no_proxy’ or ‘NO_PROXY’ for it.
Calling this method resets all existing sessions.
# File lib/httpclient.rb, line 426
426: def no_proxy=(no_proxy)
427: @no_proxy = no_proxy
428: reset_all
429: end
Sends OPTIONS request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 610
610: def options(uri, extheader = {}, &block)
611: request(:options, uri, nil, nil, extheader, &block)
612: end
Sends OPTIONS request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 701
701: def options_async(uri, extheader = {})
702: request_async(:options, uri, nil, nil, extheader)
703: end
Sends POST request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 595
595: def post(uri, body = '', extheader = {}, &block)
596: request(:post, uri, nil, body, extheader, &block)
597: end
Sends POST request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 683
683: def post_async(uri, body = nil, extheader = {})
684: request_async(:post, uri, nil, body, extheader)
685: end
Posts a content.
| uri | a String or an URI object which represents an URL of web resource. |
| body | a Hash or an Array of body part. e.g. { “a” => “b” } => ‘a=b’. Give an array to pass multiple value like
When you pass a File as a value, it will be posted as a multipart/form-data. e.g. { ‘upload’ => file } |
| extheader | a Hash or an Array of extra headers. e.g. { ‘Accept’ => ‘/’ } or [[‘Accept’, ‘image/jpeg’], [‘Accept’, ‘image/png’]]. |
| &block | Give a block to get chunked message-body of response like post_content(uri) { |chunked_body| … }. Size of each chunk may not be the same. |
post_content follows HTTP redirect status (see HTTP::Status.redirect?) internally and try to post the content to redirected URL. See redirect_uri_callback= how HTTP redirection is handled.
If you need to get full HTTP response including HTTP status and headers, use post method.
# File lib/httpclient.rb, line 544
544: def post_content(uri, body = nil, extheader = {}, &block)
545: follow_redirect(:post, uri, nil, body, extheader, &block).content
546: end
Sends PROPFIND request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 615
615: def propfind(uri, extheader = PROPFIND_DEFAULT_EXTHEADER, &block)
616: request(:propfind, uri, nil, nil, extheader, &block)
617: end
Sends PROPFIND request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 707
707: def propfind_async(uri, extheader = PROPFIND_DEFAULT_EXTHEADER)
708: request_async(:propfind, uri, nil, nil, extheader)
709: end
Sends PROPPATCH request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 620
620: def proppatch(uri, body = nil, extheader = {}, &block)
621: request(:proppatch, uri, nil, body, extheader, &block)
622: end
Sends PROPPATCH request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 713
713: def proppatch_async(uri, body = nil, extheader = {})
714: request_async(:proppatch, uri, nil, body, extheader)
715: end
Returns URI object of HTTP proxy if exists.
# File lib/httpclient.rb, line 376
376: def proxy
377: @proxy
378: end
Sets HTTP proxy used for HTTP connection. Given proxy can be an URI, a String or nil. You can set user/password for proxy authentication like HTTPClient#proxy = ‘user:passwd@myproxy:8080‘
You can use environment variable ‘http_proxy’ or ‘HTTP_PROXY’ for it. You need to use ‘cgi_http_proxy’ or ‘CGI_HTTP_PROXY’ instead if you run HTTPClient from CGI environment from security reason. (HTTPClient checks ‘REQUEST_METHOD’ environment variable whether it’s CGI or not)
Calling this method resets all existing sessions.
# File lib/httpclient.rb, line 390
390: def proxy=(proxy)
391: if proxy.nil?
392: @proxy = nil
393: @proxy_auth.reset_challenge
394: else
395: @proxy = urify(proxy)
396: if @proxy.scheme == nil or @proxy.scheme.downcase != 'http' or
397: @proxy.host == nil or @proxy.port == nil
398: raise ArgumentError.new("unsupported proxy #{proxy}")
399: end
400: @proxy_auth.reset_challenge
401: if @proxy.user || @proxy.password
402: @proxy_auth.set_auth(@proxy.user, @proxy.password)
403: end
404: end
405: reset_all
406: @session_manager.proxy = @proxy
407: @proxy
408: end
Sends PUT request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 600
600: def put(uri, body = '', extheader = {}, &block)
601: request(:put, uri, nil, body, extheader, &block)
602: end
Sends PUT request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 689
689: def put_async(uri, body = nil, extheader = {})
690: request_async(:put, uri, nil, body, extheader)
691: end
Sets callback proc when HTTP redirect status is returned for get_content and post_content. default_redirect_uri_callback is used by default.
If you need strict implementation which does not allow relative URI redirection, set strict_redirect_uri_callback instead.
clnt.redirect_uri_callback = clnt.method(:strict_redirect_uri_callback)
# File lib/httpclient.rb, line 493
493: def redirect_uri_callback=(redirect_uri_callback)
494: @redirect_uri_callback = redirect_uri_callback
495: end
Sends a request to the specified URL.
| method | HTTP method to be sent. method.to_s.upcase is used. |
| uri | a String or an URI object which represents an URL of web resource. |
| query | a Hash or an Array of query part of URL. e.g. { “a” => “b” } => ‘host/part?a=b’ Give an array to pass multiple value like
|
| body | a Hash or an Array of body part. e.g. { “a” => “b” } => ‘a=b’. Give an array to pass multiple value like
When the given method is ‘POST’ and the given body contains a file as a value, it will be posted as a multipart/form-data. e.g. { ‘upload’ => file } See HTTP::Message.file? for actual condition of ‘a file’. |
| extheader | a Hash or an Array of extra headers. e.g. { ‘Accept’ => ‘/’ } or [[‘Accept’, ‘image/jpeg’], [‘Accept’, ‘image/png’]]. |
| &block | Give a block to get chunked message-body of response like get(uri) { |chunked_body| … }. Size of each chunk may not be the same. |
You can also pass a String as a body. HTTPClient just sends a String as a HTTP request message body.
When you pass an IO as a body, HTTPClient sends it as a HTTP request with chunked encoding (Transfer-Encoding: chunked in HTTP header). Bear in mind that some server application does not support chunked request. At least cgi.rb does not support it.
# File lib/httpclient.rb, line 659
659: def request(method, uri, query = nil, body = nil, extheader = {}, &block)
660: uri = urify(uri)
661: if block
662: filtered_block = proc { |res, str|
663: block.call(str)
664: }
665: end
666: do_request(method, uri, query, body, extheader, &filtered_block)
667: end
Sends a request in async style. request method creates new Thread for HTTP connection and returns a HTTPClient::Connection instance immediately.
Arguments definition is the same as request.
# File lib/httpclient.rb, line 727
727: def request_async(method, uri, query = nil, body = nil, extheader = {})
728: uri = urify(uri)
729: do_request_async(method, uri, query, body, extheader)
730: end
Resets internal session for the given URL. Keep-alive connection for the site (host-port pair) is disconnected if exists.
# File lib/httpclient.rb, line 734
734: def reset(uri)
735: uri = urify(uri)
736: @session_manager.reset(uri)
737: end
Resets all of internal sessions. Keep-alive connections are disconnected.
# File lib/httpclient.rb, line 740
740: def reset_all
741: @session_manager.reset_all
742: end
Sets credential for Web server authentication.
| domain | a String or an URI to specify where HTTPClient should use this |
credential. If you set uri to nil, HTTPClient uses this credential
wherever a server requires it.
| user | username String. |
| passwd | password String. |
You can set multiple credentials for each uri.
clnt.set_auth('http://www.example.com/foo/', 'foo_user', 'passwd')
clnt.set_auth('http://www.example.com/bar/', 'bar_user', 'passwd')
Calling this method resets all existing sessions.
# File lib/httpclient.rb, line 444
444: def set_auth(domain, user, passwd)
445: uri = urify(domain)
446: @www_auth.set_auth(uri, user, passwd)
447: reset_all
448: end
Deprecated. Use set_auth instead.
# File lib/httpclient.rb, line 451
451: def set_basic_auth(domain, user, passwd)
452: uri = urify(domain)
453: @www_auth.basic_auth.set(uri, user, passwd)
454: reset_all
455: end
Sets credential for Proxy authentication.
| user | username String. |
| passwd | password String. |
Calling this method resets all existing sessions.
# File lib/httpclient.rb, line 462
462: def set_proxy_auth(user, passwd)
463: @proxy_auth.set_auth(user, passwd)
464: reset_all
465: end
A method for redirect uri callback. How to use:
clnt.redirect_uri_callback = clnt.method(:strict_redirect_uri_callback)
This callback does not allow relative redirect such as
Location: ../foo/
in HTTP header. (raises BadResponseError instead)
# File lib/httpclient.rb, line 553
553: def strict_redirect_uri_callback(uri, res)
554: newuri = URI.parse(res.header['location'][0])
555: if https?(uri) && !https?(newuri)
556: raise BadResponseError.new("redirecting to non-https resource")
557: end
558: unless newuri.is_a?(URI::HTTP)
559: raise BadResponseError.new("unexpected location: #{newuri}", res)
560: end
561: puts "redirect to: #{newuri}" if $DEBUG
562: newuri
563: end
Sends TRACE request to the specified URL. See request for arguments.
# File lib/httpclient.rb, line 625
625: def trace(uri, query = nil, body = nil, extheader = {}, &block)
626: request('TRACE', uri, query, body, extheader, &block)
627: end
Sends TRACE request in async style. See request_async for arguments. It immediately returns a HTTPClient::Connection instance as a result.
# File lib/httpclient.rb, line 719
719: def trace_async(uri, query = nil, body = nil, extheader = {})
720: request_async(:trace, uri, query, body, extheader)
721: end
# File lib/httpclient.rb, line 896
896: def create_boundary
897: Digest::SHA1.hexdigest(Time.now.to_s)
898: end
# File lib/httpclient.rb, line 854
854: def create_request(method, uri, query, body, extheader)
855: method = method.to_s.upcase
856: if extheader.is_a?(Hash)
857: extheader = extheader.to_a
858: else
859: extheader = extheader.dup
860: end
861: boundary = nil
862: if body
863: dummy, content_type = extheader.find { |key, value|
864: key.downcase == 'content-type'
865: }
866: if content_type
867: if /\Amultipart/ =~ content_type
868: if content_type =~ /boundary=(.+)\z/
869: boundary = $1
870: else
871: boundary = create_boundary
872: content_type = "#{content_type}; boundary=#{boundary}"
873: extheader = override_header(extheader, 'Content-Type', content_type)
874: end
875: end
876: elsif method == 'POST'
877: if file_in_form_data?(body)
878: boundary = create_boundary
879: content_type = "multipart/form-data; boundary=#{boundary}"
880: else
881: content_type = 'application/x-www-form-urlencoded'
882: end
883: extheader << ['Content-Type', content_type]
884: end
885: end
886: req = HTTP::Message.new_request(method, uri, query, body, boundary)
887: extheader.each do |key, value|
888: req.header.add(key, value)
889: end
890: if @cookie_manager && cookie = @cookie_manager.find(uri)
891: req.header.add('Cookie', cookie)
892: end
893: req
894: end
!! CAUTION !!
Method 'do_get*' runs under MT conditon. Be careful to change.
# File lib/httpclient.rb, line 941
941: def do_get_block(req, proxy, conn, &block)
942: @request_filter.each do |filter|
943: filter.filter_request(req)
944: end
945: if str = @test_loopback_response.shift
946: dump_dummy_request_response(req.body.dump, str) if @debug_dev
947: conn.push(HTTP::Message.new_response(str))
948: return
949: end
950: content = block ? nil : ''
951: res = HTTP::Message.new_response(content)
952: @debug_dev << "= Request\n\n" if @debug_dev
953: sess = @session_manager.query(req, proxy)
954: res.peer_cert = sess.ssl_peer_cert
955: @debug_dev << "\n\n= Response\n\n" if @debug_dev
956: do_get_header(req, res, sess)
957: conn.push(res)
958: sess.get_body do |part|
959: if block
960: block.call(res, part)
961: else
962: content << part
963: end
964: end
965: @session_manager.keep(sess) unless sess.closed?
966: commands = @request_filter.collect { |filter|
967: filter.filter_response(req, res)
968: }
969: if commands.find { |command| command == :retry }
970: raise RetryableResponse.new
971: end
972: end
# File lib/httpclient.rb, line 1002
1002: def do_get_header(req, res, sess)
1003: res.version, res.status, res.reason, headers = sess.get_header
1004: headers.each do |key, value|
1005: res.header.add(key, value)
1006: end
1007: if @cookie_manager
1008: res.header['set-cookie'].each do |cookie|
1009: @cookie_manager.parse(cookie, req.header.request_uri)
1010: end
1011: end
1012: end
# File lib/httpclient.rb, line 974
974: def do_get_stream(req, proxy, conn)
975: @request_filter.each do |filter|
976: filter.filter_request(req)
977: end
978: if str = @test_loopback_response.shift
979: dump_dummy_request_response(req.body.dump, str) if @debug_dev
980: conn.push(HTTP::Message.new_response(StringIO.new(str)))
981: return
982: end
983: piper, pipew = IO.pipe
984: res = HTTP::Message.new_response(piper)
985: @debug_dev << "= Request\n\n" if @debug_dev
986: sess = @session_manager.query(req, proxy)
987: res.peer_cert = sess.ssl_peer_cert
988: @debug_dev << "\n\n= Response\n\n" if @debug_dev
989: do_get_header(req, res, sess)
990: conn.push(res)
991: sess.get_body do |part|
992: pipew.syswrite(part)
993: end
994: pipew.close
995: @session_manager.keep(sess) unless sess.closed?
996: commands = @request_filter.collect { |filter|
997: filter.filter_response(req, res)
998: }
999: # ignore commands (not retryable in async mode)
1000: end
# File lib/httpclient.rb, line 752
752: def do_request(method, uri, query, body, extheader, &block)
753: conn = Connection.new
754: res = nil
755: if HTTP::Message.file?(body)
756: pos = body.pos rescue nil
757: end
758: retry_count = @session_manager.protocol_retry_count
759: proxy = no_proxy?(uri) ? nil : @proxy
760: while retry_count > 0
761: body.pos = pos if pos
762: req = create_request(method, uri, query, body, extheader)
763: begin
764: protect_keep_alive_disconnected do
765: do_get_block(req, proxy, conn, &block)
766: end
767: res = conn.pop
768: break
769: rescue RetryableResponse
770: res = conn.pop
771: retry_count -= 1
772: end
773: end
774: res
775: end
# File lib/httpclient.rb, line 777
777: def do_request_async(method, uri, query, body, extheader)
778: conn = Connection.new
779: t = Thread.new(conn) { |tconn|
780: if HTTP::Message.file?(body)
781: pos = body.pos rescue nil
782: end
783: retry_count = @session_manager.protocol_retry_count
784: proxy = no_proxy?(uri) ? nil : @proxy
785: while retry_count > 0
786: body.pos = pos if pos
787: req = create_request(method, uri, query, body, extheader)
788: begin
789: protect_keep_alive_disconnected do
790: do_get_stream(req, proxy, tconn)
791: end
792: break
793: rescue RetryableResponse
794: retry_count -= 1
795: end
796: end
797: }
798: conn.async_thread = t
799: conn
800: end
# File lib/httpclient.rb, line 1014
1014: def dump_dummy_request_response(req, res)
1015: @debug_dev << "= Dummy Request\n\n"
1016: @debug_dev << req
1017: @debug_dev << "\n\n= Dummy Response\n\n"
1018: @debug_dev << res
1019: end
# File lib/httpclient.rb, line 900
900: def file_in_form_data?(body)
901: HTTP::Message.multiparam_query?(body) &&
902: body.any? { |k, v| HTTP::Message.file?(v) }
903: end
# File lib/httpclient.rb, line 820
820: def follow_redirect(method, uri, query, body, extheader, &block)
821: uri = urify(uri)
822: if block
823: filtered_block = proc { |r, str|
824: block.call(str) if HTTP::Status.successful?(r.status)
825: }
826: end
827: if HTTP::Message.file?(body)
828: pos = body.pos rescue nil
829: end
830: retry_number = 0
831: while retry_number < @follow_redirect_count
832: body.pos = pos if pos
833: res = do_request(method, uri, query, body, extheader, &filtered_block)
834: if HTTP::Status.successful?(res.status)
835: return res
836: elsif HTTP::Status.redirect?(res.status)
837: uri = urify(@redirect_uri_callback.call(uri, res))
838: retry_number += 1
839: else
840: raise BadResponseError.new("unexpected response: #{res.header.inspect}", res)
841: end
842: end
843: raise BadResponseError.new("retry count exceeded", res)
844: end
# File lib/httpclient.rb, line 816
816: def getenv(name)
817: ENV[name.downcase] || ENV[name.upcase]
818: end
# File lib/httpclient.rb, line 935
935: def https?(uri)
936: uri.scheme.downcase == 'https'
937: end
# File lib/httpclient.rb, line 802
802: def load_environment
803: # http_proxy
804: if getenv('REQUEST_METHOD')
805: # HTTP_PROXY conflicts with the environment variable usage in CGI where
806: # HTTP_* is used for HTTP header information. Unlike open-uri, we
807: # simply ignore http_proxy in CGI env and use cgi_http_proxy instead.
808: self.proxy = getenv('cgi_http_proxy')
809: else
810: self.proxy = getenv('http_proxy')
811: end
812: # no_proxy
813: self.no_proxy = getenv('no_proxy')
814: end
# File lib/httpclient.rb, line 919
919: def no_proxy?(uri)
920: if !@proxy or NO_PROXY_HOSTS.include?(uri.host)
921: return true
922: end
923: unless @no_proxy
924: return false
925: end
926: @no_proxy.scan(/([^:,]+)(?::(\d+))?/) do |host, port|
927: if /(\A|\.)#{Regexp.quote(host)}\z/ =~ uri.host &&
928: (!port || uri.port == port.to_i)
929: return true
930: end
931: end
932: false
933: end
# File lib/httpclient.rb, line 905
905: def override_header(extheader, key, value)
906: result = []
907: extheader.each do |k, v|
908: if k.downcase == key.downcase
909: result << [key, value]
910: else
911: result << [k, v]
912: end
913: end
914: result
915: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.