1# frozen_string_literal: false
2#
3# = net/http.rb
4#
5# Copyright (c) 1999-2007 Yukihiro Matsumoto
6# Copyright (c) 1999-2007 Minero Aoki
7# Copyright (c) 2001 GOTOU Yuuzou
8#
9# Written and maintained by Minero Aoki <aamine@loveruby.net>.
10# HTTPS support added by GOTOU Yuuzou <gotoyuzo@notwork.org>.
11#
12# This file is derived from "http-access.rb".
13#
14# Documented by Minero Aoki; converted to RDoc by William Webber.
15#
16# This program is free software. You can re-distribute and/or
17# modify this program under the same terms of ruby itself ---
18# Ruby Distribution License or GNU General Public License.
19#
20# See Net::HTTP for an overview and examples.
21#
22
23require_relative 'protocol'
24require 'uri'
25autoload :OpenSSL, 'openssl'
26
27module Net   #:nodoc:
28
29  # :stopdoc:
30  class HTTPBadResponse < StandardError; end
31  class HTTPHeaderSyntaxError < StandardError; end
32  # :startdoc:
33
34  # == An HTTP client API for Ruby.
35  #
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).
39  #
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.
43  #
44  # If you are only performing a few GET requests you should try OpenURI.
45  #
46  # == Simple Examples
47  #
48  # All examples assume you have loaded Net::HTTP with:
49  #
50  #   require 'net/http'
51  #
52  # This will also require 'uri' so you don't need to require it separately.
53  #
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.
57  #
58  # === GET
59  #
60  #   Net::HTTP.get('example.com', '/index.html') # => String
61  #
62  # === GET by URI
63  #
64  #   uri = URI('http://example.com/index.html?count=10')
65  #   Net::HTTP.get(uri) # => String
66  #
67  # === GET with Dynamic Parameters
68  #
69  #   uri = URI('http://example.com/index.html')
70  #   params = { :limit => 10, :page => 3 }
71  #   uri.query = URI.encode_www_form(params)
72  #
73  #   res = Net::HTTP.get_response(uri)
74  #   puts res.body if res.is_a?(Net::HTTPSuccess)
75  #
76  # === POST
77  #
78  #   uri = URI('http://www.example.com/search.cgi')
79  #   res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
80  #   puts res.body
81  #
82  # === POST with Multiple Values
83  #
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
87  #
88  # == How to use Net::HTTP
89  #
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.
93  #
94  #   uri = URI('http://example.com/some_path?query=string')
95  #
96  #   Net::HTTP.start(uri.host, uri.port) do |http|
97  #     request = Net::HTTP::Get.new uri
98  #
99  #     response = http.request request # Net::HTTPResponse object
100  #   end
101  #
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.
106  #
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.
110  #
111  # The request types Net::HTTP supports are listed below in the section "HTTP
112  # Request Classes".
113  #
114  # For all the Net::HTTP request objects and shortcut request methods you may
115  # supply either a String for the request path or a URI from which Net::HTTP
116  # will extract the request path.
117  #
118  # === Response Data
119  #
120  #   uri = URI('http://example.com/index.html')
121  #   res = Net::HTTP.get_response(uri)
122  #
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}"
128  #
129  #   # Status
130  #   puts res.code       # => '200'
131  #   puts res.message    # => 'OK'
132  #   puts res.class.name # => 'HTTPOK'
133  #
134  #   # Body
135  #   puts res.body if res.response_body_permitted?
136  #
137  # === Following Redirection
138  #
139  # Each Net::HTTPResponse object belongs to a class for its response code.
140  #
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.
146  #
147  # Using a case statement you can handle various types of responses properly:
148  #
149  #   def fetch(uri_str, limit = 10)
150  #     # You should choose a better exception.
151  #     raise ArgumentError, 'too many HTTP redirects' if limit == 0
152  #
153  #     response = Net::HTTP.get_response(URI(uri_str))
154  #
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
166  #
167  #   print fetch('http://www.ruby-lang.org')
168  #
169  # === POST
170  #
171  # A POST can be made using the Net::HTTP::Post request class.  This example
172  # creates a URL encoded POST body:
173  #
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')
177  #
178  #   res = Net::HTTP.start(uri.hostname, uri.port) do |http|
179  #     http.request(req)
180  #   end
181  #
182  #   case res
183  #   when Net::HTTPSuccess, Net::HTTPRedirection
184  #     # OK
185  #   else
186  #     res.value
187  #   end
188  #
189  # To send multipart/form-data use Net::HTTPHeader#set_form:
190  #
191  #   req = Net::HTTP::Post.new(uri)
192  #   req.set_form([['upload', File.open('foo.bar')]], 'multipart/form-data')
193  #
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).
196  #
197  # === Setting Headers
198  #
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.
203  #
204  #   uri = URI('http://example.com/cached_response')
205  #   file = File.stat 'cached_response'
206  #
207  #   req = Net::HTTP::Get.new(uri)
208  #   req['If-Modified-Since'] = file.mtime.rfc2822
209  #
210  #   res = Net::HTTP.start(uri.hostname, uri.port) {|http|
211  #     http.request(req)
212  #   }
213  #
214  #   open 'cached_response', 'w' do |io|
215  #     io.write res.body
216  #   end if res.is_a?(Net::HTTPSuccess)
217  #
218  # === Basic Authentication
219  #
220  # 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')
224  #
225  #   req = Net::HTTP::Get.new(uri)
226  #   req.basic_auth 'user', 'pass'
227  #
228  #   res = Net::HTTP.start(uri.hostname, uri.port) {|http|
229  #     http.request(req)
230  #   }
231  #   puts res.body
232  #
233  # === Streaming Response Bodies
234  #
235  # By default Net::HTTP reads an entire response into memory.  If you are
236  # handling large files or wish to implement a progress bar you can instead
237  # stream the body directly to an IO.
238  #
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
248  #         end
249  #       end
250  #     end
251  #   end
252  #
253  # === HTTPS
254  #
255  # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=.
256  #
257  #   uri = URI('https://secure.example.com/some_path?query=string')
258  #
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
262  #   end
263  #
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.
267  #
268  #   uri = URI('https://example.com/')
269  #   Net::HTTP.get(uri) # => String
270  #
271  # In previous versions of Ruby you would need to require 'net/https' to use
272  # HTTPS. This is no longer true.
273  #
274  # === Proxies
275  #
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.
387  #
388  class HTTP < Protocol
389
390    # :stopdoc:
391    Revision = %q$Revision: 66401 $.split[1]
392    HTTPVersion = '1.1'
393    begin
394      require 'zlib'
395      require 'stringio'  #for our purposes (unpacking gzip) lump these together
396      HAVE_ZLIB=true
397    rescue LoadError
398      HAVE_ZLIB=false
399    end
400    # :startdoc:
401
402    # Turns on net/http 1.2 (Ruby 1.8) features.
403    # Defaults to ON in Ruby 1.8 or later.
404    def HTTP.version_1_2
405      true
406    end
407
408    # Returns true if net/http is in version 1.2 mode.
409    # Defaults to true.
410    def HTTP.version_1_2?
411      true
412    end
413
414    def HTTP.version_1_1?  #:nodoc:
415      false
416    end
417
418    class << HTTP
419      alias is_version_1_1? version_1_1?   #:nodoc:
420      alias is_version_1_2? version_1_2?   #:nodoc:
421    end
422
423    #
424    # short cut methods
425    #
426
427    #
428    # Gets the body text from the target and outputs it to $stdout.  The
429    # target can either be specified as
430    # (+uri+), or as (+host+, +path+, +port+ = 80); so:
431    #
432    #    Net::HTTP.get_print URI('http://www.example.com/index.html')
433    #
434    # or:
435    #
436    #    Net::HTTP.get_print 'www.example.com', '/index.html'
437    #
438    def HTTP.get_print(uri_or_host, path = nil, port = nil)
439      get_response(uri_or_host, path, port) {|res|
440        res.read_body do |chunk|
441          $stdout.print chunk
442        end
443      }
444      nil
445    end
446
447    # Sends a GET request to the target and returns the HTTP response
448    # as a string.  The target can either be specified as
449    # (+uri+), or as (+host+, +path+, +port+ = 80); so:
450    #
451    #    print Net::HTTP.get(URI('http://www.example.com/index.html'))
452    #
453    # or:
454    #
455    #    print Net::HTTP.get('www.example.com', '/index.html')
456    #
457    def HTTP.get(uri_or_host, path = nil, port = nil)
458      get_response(uri_or_host, path, port).body
459    end
460
461    # Sends a GET request to the target and returns the HTTP response
462    # as a Net::HTTPResponse object.  The target can either be specified as
463    # (+uri+), or as (+host+, +path+, +port+ = 80); so:
464    #
465    #    res = Net::HTTP.get_response(URI('http://www.example.com/index.html'))
466    #    print res.body
467    #
468    # or:
469    #
470    #    res = Net::HTTP.get_response('www.example.com', '/index.html')
471    #    print res.body
472    #
473    def HTTP.get_response(uri_or_host, path = nil, port = nil, &block)
474      if path
475        host = uri_or_host
476        new(host, port || HTTP.default_port).start {|http|
477          return http.request_get(path, &block)
478        }
479      else
480        uri = uri_or_host
481        start(uri.hostname, uri.port,
482              :use_ssl => uri.scheme == 'https') {|http|
483          return http.request_get(uri, &block)
484        }
485      end
486    end
487
488    # Posts data to the specified URI object.
489    #
490    # Example:
491    #
492    #   require 'net/http'
493    #   require 'uri'
494    #
495    #   Net::HTTP.post URI('http://www.example.com/api/search'),
496    #                  { "q" => "ruby", "max" => "50" }.to_json,
497    #                  "Content-Type" => "application/json"
498    #
499    def HTTP.post(url, data, header = nil)
500      start(url.hostname, url.port,
501            :use_ssl => url.scheme == 'https' ) {|http|
502        http.post(url, data, header)
503      }
504    end
505
506    # Posts HTML form data to the specified URI object.
507    # The form data must be provided as a Hash mapping from String to String.
508    # Example:
509    #
510    #   { "cmd" => "search", "q" => "ruby", "max" => "50" }
511    #
512    # This method also does Basic Authentication iff +url+.user exists.
513    # But userinfo for authentication is deprecated (RFC3986).
514    # So this feature will be removed.
515    #
516    # Example:
517    #
518    #   require 'net/http'
519    #   require 'uri'
520    #
521    #   Net::HTTP.post_form URI('http://www.example.com/search.cgi'),
522    #                       { "q" => "ruby", "max" => "50" }
523    #
524    def HTTP.post_form(url, params)
525      req = Post.new(url)
526      req.form_data = params
527      req.basic_auth url.user, url.password if url.user
528      start(url.hostname, url.port,
529            :use_ssl => url.scheme == 'https' ) {|http|
530        http.request(req)
531      }
532    end
533
534    #
535    # HTTP session management
536    #
537
538    # The default port to use for HTTP requests; defaults to 80.
539    def HTTP.default_port
540      http_default_port()
541    end
542
543    # The default port to use for HTTP requests; defaults to 80.
544    def HTTP.http_default_port
545      80
546    end
547
548    # The default port to use for HTTPS requests; defaults to 443.
549    def HTTP.https_default_port
550      443
551    end
552
553    def HTTP.socket_type   #:nodoc: obsolete
554      BufferedIO
555    end
556
557    # :call-seq:
558    #   HTTP.start(address, port, p_addr, p_port, p_user, p_pass, &block)
559    #   HTTP.start(address, port=nil, p_addr=:ENV, p_port=nil, p_user=nil, p_pass=nil, opt, &block)
560    #
561    # Creates a new Net::HTTP object, then additionally opens the TCP
562    # connection and HTTP session.
563    #
564    # Arguments are the following:
565    # _address_ :: hostname or IP address of the server
566    # _port_    :: port of the server
567    # _p_addr_  :: address of proxy
568    # _p_port_  :: port of proxy
569    # _p_user_  :: user of proxy
570    # _p_pass_  :: pass of proxy
571    # _opt_     :: optional hash
572    #
573    # _opt_ sets following values by its accessor.
574    # The keys are ca_file, ca_path, cert, cert_store, ciphers,
575    # close_on_empty_response, key, open_timeout, read_timeout, write_timeout, ssl_timeout,
576    # ssl_version, use_ssl, verify_callback, verify_depth and verify_mode.
577    # If you set :use_ssl as true, you can use https and default value of
578    # verify_mode is set as OpenSSL::SSL::VERIFY_PEER.
579    #
580    # If the optional block is given, the newly
581    # created Net::HTTP object is passed to it and closed when the
582    # block finishes.  In this case, the return value of this method
583    # is the return value of the block.  If no block is given, the
584    # return value of this method is the newly created Net::HTTP object
585    # itself, and the caller is responsible for closing it upon completion
586    # using the finish() method.
587    def HTTP.start(address, *arg, &block) # :yield: +http+
588      arg.pop if opt = Hash.try_convert(arg[-1])
589      port, p_addr, p_port, p_user, p_pass = *arg
590      p_addr = :ENV if arg.size < 2
591      port = https_default_port if !port && opt && opt[:use_ssl]
592      http = new(address, port, p_addr, p_port, p_user, p_pass)
593
594      if opt
595        if opt[:use_ssl]
596          opt = {verify_mode: OpenSSL::SSL::VERIFY_PEER}.update(opt)
597        end
598        http.methods.grep(/\A(\w+)=\z/) do |meth|
599          key = $1.to_sym
600          opt.key?(key) or next
601          http.__send__(meth, opt[key])
602        end
603      end
604
605      http.start(&block)
606    end
607
608    class << HTTP
609      alias newobj new # :nodoc:
610    end
611
612    # Creates a new Net::HTTP object without opening a TCP connection or
613    # HTTP session.
614    #
615    # The +address+ should be a DNS hostname or IP address, the +port+ is the
616    # port the server operates on.  If no +port+ is given the default port for
617    # HTTP or HTTPS is used.
618    #
619    # If none of the +p_+ arguments are given, the proxy host and port are
620    # taken from the +http_proxy+ environment variable (or its uppercase
621    # equivalent) if present.  If the proxy requires authentication you must
622    # supply it by hand.  See URI::Generic#find_proxy for details of proxy
623    # detection from the environment.  To disable proxy detection set +p_addr+
624    # to nil.
625    #
626    # If you are connecting to a custom proxy, +p_addr+ specifies the DNS name
627    # or IP address of the proxy host, +p_port+ the port to use to access the
628    # proxy, +p_user+ and +p_pass+ the username and password if authorization
629    # is required to use the proxy, and p_no_proxy hosts which do not
630    # use the proxy.
631    #
632    def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
633      http = super address, port
634
635      if proxy_class? then # from Net::HTTP::Proxy()
636        http.proxy_from_env = @proxy_from_env
637        http.proxy_address  = @proxy_address
638        http.proxy_port     = @proxy_port
639        http.proxy_user     = @proxy_user
640        http.proxy_pass     = @proxy_pass
641      elsif p_addr == :ENV then
642        http.proxy_from_env = true
643      else
644        if p_addr && p_no_proxy && !URI::Generic.use_proxy?(p_addr, p_addr, p_port, p_no_proxy)
645          p_addr = nil
646          p_port = nil
647        end
648        http.proxy_address = p_addr
649        http.proxy_port    = p_port || default_port
650        http.proxy_user    = p_user
651        http.proxy_pass    = p_pass
652      end
653
654      http
655    end
656
657    # Creates a new Net::HTTP object for the specified server address,
658    # without opening the TCP connection or initializing the HTTP session.
659    # The +address+ should be a DNS hostname or IP address.
660    def initialize(address, port = nil)
661      @address = address
662      @port    = (port || HTTP.default_port)
663      @local_host = nil
664      @local_port = nil
665      @curr_http_version = HTTPVersion
666      @keep_alive_timeout = 2
667      @last_communicated = nil
668      @close_on_empty_response = false
669      @socket  = nil
670      @started = false
671      @open_timeout = 60
672      @read_timeout = 60
673      @write_timeout = 60
674      @continue_timeout = nil
675      @max_retries = 1
676      @debug_output = nil
677
678      @proxy_from_env = false
679      @proxy_uri      = nil
680      @proxy_address  = nil
681      @proxy_port     = nil
682      @proxy_user     = nil
683      @proxy_pass     = nil
684
685      @use_ssl = false
686      @ssl_context = nil
687      @ssl_session = nil
688      @sspi_enabled = false
689      SSL_IVNAMES.each do |ivname|
690        instance_variable_set ivname, nil
691      end
692    end
693
694    def inspect
695      "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
696    end
697
698    # *WARNING* This method opens a serious security hole.
699    # Never use this method in production code.
700    #
701    # Sets an output stream for debugging.
702    #
703    #   http = Net::HTTP.new(hostname)
704    #   http.set_debug_output $stderr
705    #   http.start { .... }
706    #
707    def set_debug_output(output)
708      warn 'Net::HTTP#set_debug_output called after HTTP started', uplevel: 1 if started?
709      @debug_output = output
710    end
711
712    # The DNS host name or IP address to connect to.
713    attr_reader :address
714
715    # The port number to connect to.
716    attr_reader :port
717
718    # The local host used to establish the connection.
719    attr_accessor :local_host
720
721    # The local port used to establish the connection.
722    attr_accessor :local_port
723
724    attr_writer :proxy_from_env
725    attr_writer :proxy_address
726    attr_writer :proxy_port
727    attr_writer :proxy_user
728    attr_writer :proxy_pass
729
730    # Number of seconds to wait for the connection to open. Any number
731    # may be used, including Floats for fractional seconds. If the HTTP
732    # object cannot open a connection in this many seconds, it raises a
733    # Net::OpenTimeout exception. The default value is 60 seconds.
734    attr_accessor :open_timeout
735
736    # Number of seconds to wait for one block to be read (via one read(2)
737    # call). Any number may be used, including Floats for fractional
738    # seconds. If the HTTP object cannot read data in this many seconds,
739    # it raises a Net::ReadTimeout exception. The default value is 60 seconds.
740    attr_reader :read_timeout
741
742    # Number of seconds to wait for one block to be written (via one write(2)
743    # call). Any number may be used, including Floats for fractional
744    # seconds. If the HTTP object cannot write data in this many seconds,
745    # it raises a Net::WriteTimeout exception. The default value is 60 seconds.
746    # Net::WriteTimeout is not raised on Windows.
747    attr_reader :write_timeout
748
749    # Maximum number of times to retry an idempotent request in case of
750    # Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET,
751    # Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError,
752    # Timeout::Error.
753    # Should be a non-negative integer number. Zero means no retries.
754    # The default value is 1.
755    def max_retries=(retries)
756      retries = retries.to_int
757      if retries < 0
758        raise ArgumentError, 'max_retries should be non-negative integer number'
759      end
760      @max_retries = retries
761    end
762
763    attr_reader :max_retries
764
765    # Setter for the read_timeout attribute.
766    def read_timeout=(sec)
767      @socket.read_timeout = sec if @socket
768      @read_timeout = sec
769    end
770
771    # Setter for the write_timeout attribute.
772    def write_timeout=(sec)
773      @socket.write_timeout = sec if @socket
774      @write_timeout = sec
775    end
776
777    # Seconds to wait for 100 Continue response. If the HTTP object does not
778    # receive a response in this many seconds it sends the request body. The
779    # default value is +nil+.
780    attr_reader :continue_timeout
781
782    # Setter for the continue_timeout attribute.
783    def continue_timeout=(sec)
784      @socket.continue_timeout = sec if @socket
785      @continue_timeout = sec
786    end
787
788    # Seconds to reuse the connection of the previous request.
789    # If the idle time is less than this Keep-Alive Timeout,
790    # Net::HTTP reuses the TCP/IP socket used by the previous communication.
791    # The default value is 2 seconds.
792    attr_accessor :keep_alive_timeout
793
794    # Returns true if the HTTP session has been started.
795    def started?
796      @started
797    end
798
799    alias active? started?   #:nodoc: obsolete
800
801    attr_accessor :close_on_empty_response
802
803    # Returns true if SSL/TLS is being used with HTTP.
804    def use_ssl?
805      @use_ssl
806    end
807
808    # Turn on/off SSL.
809    # This flag must be set before starting session.
810    # If you change use_ssl value after session started,
811    # a Net::HTTP object raises IOError.
812    def use_ssl=(flag)
813      flag = flag ? true : false
814      if started? and @use_ssl != flag
815        raise IOError, "use_ssl value changed, but session already started"
816      end
817      @use_ssl = flag
818    end
819
820    SSL_IVNAMES = [
821      :@ca_file,
822      :@ca_path,
823      :@cert,
824      :@cert_store,
825      :@ciphers,
826      :@key,
827      :@ssl_timeout,
828      :@ssl_version,
829      :@min_version,
830      :@max_version,
831      :@verify_callback,
832      :@verify_depth,
833      :@verify_mode,
834    ]
835    SSL_ATTRIBUTES = [
836      :ca_file,
837      :ca_path,
838      :cert,
839      :cert_store,
840      :ciphers,
841      :key,
842      :ssl_timeout,
843      :ssl_version,
844      :min_version,
845      :max_version,
846      :verify_callback,
847      :verify_depth,
848      :verify_mode,
849    ]
850
851    # Sets path of a CA certification file in PEM format.
852    #
853    # The file can contain several CA certificates.
854    attr_accessor :ca_file
855
856    # Sets path of a CA certification directory containing certifications in
857    # PEM format.
858    attr_accessor :ca_path
859
860    # Sets an OpenSSL::X509::Certificate object as client certificate.
861    # (This method is appeared in Michal Rokos's OpenSSL extension).
862    attr_accessor :cert
863
864    # Sets the X509::Store to verify peer certificate.
865    attr_accessor :cert_store
866
867    # Sets the available ciphers.  See OpenSSL::SSL::SSLContext#ciphers=
868    attr_accessor :ciphers
869
870    # Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
871    # (This method is appeared in Michal Rokos's OpenSSL extension.)
872    attr_accessor :key
873
874    # Sets the SSL timeout seconds.
875    attr_accessor :ssl_timeout
876
877    # Sets the SSL version.  See OpenSSL::SSL::SSLContext#ssl_version=
878    attr_accessor :ssl_version
879
880    # Sets the minimum SSL version.  See OpenSSL::SSL::SSLContext#min_version=
881    attr_accessor :min_version
882
883    # Sets the maximum SSL version.  See OpenSSL::SSL::SSLContext#max_version=
884    attr_accessor :max_version
885
886    # Sets the verify callback for the server certification verification.
887    attr_accessor :verify_callback
888
889    # Sets the maximum depth for the certificate chain verification.
890    attr_accessor :verify_depth
891
892    # Sets the flags for server the certification verification at beginning of
893    # SSL/TLS session.
894    #
895    # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable.
896    attr_accessor :verify_mode
897
898    # Returns the X.509 certificates the server presented.
899    def peer_cert
900      if not use_ssl? or not @socket
901        return nil
902      end
903      @socket.io.peer_cert
904    end
905
906    # Opens a TCP connection and HTTP session.
907    #
908    # When this method is called with a block, it passes the Net::HTTP
909    # object to the block, and closes the TCP connection and HTTP session
910    # after the block has been executed.
911    #
912    # When called with a block, it returns the return value of the
913    # block; otherwise, it returns self.
914    #
915    def start  # :yield: http
916      raise IOError, 'HTTP session already opened' if @started
917      if block_given?
918        begin
919          do_start
920          return yield(self)
921        ensure
922          do_finish
923        end
924      end
925      do_start
926      self
927    end
928
929    def do_start
930      connect
931      @started = true
932    end
933    private :do_start
934
935    def connect
936      if proxy? then
937        conn_address = proxy_address
938        conn_port    = proxy_port
939      else
940        conn_address = address
941        conn_port    = port
942      end
943
944      D "opening connection to #{conn_address}:#{conn_port}..."
945      s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
946        begin
947          TCPSocket.open(conn_address, conn_port, @local_host, @local_port)
948        rescue => e
949          raise e, "Failed to open TCP connection to " +
950            "#{conn_address}:#{conn_port} (#{e.message})"
951        end
952      }
953      s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
954      D "opened"
955      if use_ssl?
956        if proxy?
957          plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
958                                      write_timeout: @write_timeout,
959                                      continue_timeout: @continue_timeout,
960                                      debug_output: @debug_output)
961          buf = "CONNECT #{@address}:#{@port} HTTP/#{HTTPVersion}\r\n"
962          buf << "Host: #{@address}:#{@port}\r\n"
963          if proxy_user
964            credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0')
965            buf << "Proxy-Authorization: Basic #{credential}\r\n"
966          end
967          buf << "\r\n"
968          plain_sock.write(buf)
969          HTTPResponse.read_new(plain_sock).value
970          # assuming nothing left in buffers after successful CONNECT response
971        end
972
973        ssl_parameters = Hash.new
974        iv_list = instance_variables
975        SSL_IVNAMES.each_with_index do |ivname, i|
976          if iv_list.include?(ivname) and
977            value = instance_variable_get(ivname)
978            ssl_parameters[SSL_ATTRIBUTES[i]] = value if value
979          end
980        end
981        @ssl_context = OpenSSL::SSL::SSLContext.new
982        @ssl_context.set_params(ssl_parameters)
983        @ssl_context.session_cache_mode =
984          OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
985          OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
986        @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
987        D "starting SSL for #{conn_address}:#{conn_port}..."
988        s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
989        s.sync_close = true
990        # Server Name Indication (SNI) RFC 3546
991        s.hostname = @address if s.respond_to? :hostname=
992        if @ssl_session and
993           Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
994          s.session = @ssl_session
995        end
996        ssl_socket_connect(s, @open_timeout)
997        if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
998          s.post_connection_check(@address)
999        end
1000        D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1001      end
1002      @socket = BufferedIO.new(s, read_timeout: @read_timeout,
1003                               write_timeout: @write_timeout,
1004                               continue_timeout: @continue_timeout,
1005                               debug_output: @debug_output)
1006      on_connect
1007    rescue => exception
1008      if s
1009        D "Conn close because of connect error #{exception}"
1010        s.close
1011      end
1012      raise
1013    end
1014    private :connect
1015
1016    def on_connect
1017    end
1018    private :on_connect
1019
1020    # Finishes the HTTP session and closes the TCP connection.
1021    # Raises IOError if the session has not been started.
1022    def finish
1023      raise IOError, 'HTTP session not yet started' unless started?
1024      do_finish
1025    end
1026
1027    def do_finish
1028      @started = false
1029      @socket.close if @socket
1030      @socket = nil
1031    end
1032    private :do_finish
1033
1034    #
1035    # proxy
1036    #
1037
1038    public
1039
1040    # no proxy
1041    @is_proxy_class = false
1042    @proxy_from_env = false
1043    @proxy_addr = nil
1044    @proxy_port = nil
1045    @proxy_user = nil
1046    @proxy_pass = nil
1047
1048    # Creates an HTTP proxy class which behaves like Net::HTTP, but
1049    # performs all access via the specified proxy.
1050    #
1051    # This class is obsolete.  You may pass these same parameters directly to
1052    # Net::HTTP.new.  See Net::HTTP.new for details of the arguments.
1053    def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil)
1054      return self unless p_addr
1055
1056      Class.new(self) {
1057        @is_proxy_class = true
1058
1059        if p_addr == :ENV then
1060          @proxy_from_env = true
1061          @proxy_address = nil
1062          @proxy_port    = nil
1063        else
1064          @proxy_from_env = false
1065          @proxy_address = p_addr
1066          @proxy_port    = p_port || default_port
1067        end
1068
1069        @proxy_user = p_user
1070        @proxy_pass = p_pass
1071      }
1072    end
1073
1074    class << HTTP
1075      # returns true if self is a class which was created by HTTP::Proxy.
1076      def proxy_class?
1077        defined?(@is_proxy_class) ? @is_proxy_class : false
1078      end
1079
1080      # Address of proxy host. If Net::HTTP does not use a proxy, nil.
1081      attr_reader :proxy_address
1082
1083      # Port number of proxy host. If Net::HTTP does not use a proxy, nil.
1084      attr_reader :proxy_port
1085
1086      # User name for accessing proxy. If Net::HTTP does not use a proxy, nil.
1087      attr_reader :proxy_user
1088
1089      # User password for accessing proxy. If Net::HTTP does not use a proxy,
1090      # nil.
1091      attr_reader :proxy_pass
1092    end
1093
1094    # True if requests for this connection will be proxied
1095    def proxy?
1096      !!(@proxy_from_env ? proxy_uri : @proxy_address)
1097    end
1098
1099    # True if the proxy for this connection is determined from the environment
1100    def proxy_from_env?
1101      @proxy_from_env
1102    end
1103
1104    # The proxy URI determined from the environment for this connection.
1105    def proxy_uri # :nodoc:
1106      return if @proxy_uri == false
1107      @proxy_uri ||= URI::HTTP.new(
1108        "http".freeze, nil, address, port, nil, nil, nil, nil, nil
1109      ).find_proxy || false
1110      @proxy_uri || nil
1111    end
1112
1113    # The address of the proxy server, if one is configured.
1114    def proxy_address
1115      if @proxy_from_env then
1116        proxy_uri&.hostname
1117      else
1118        @proxy_address
1119      end
1120    end
1121
1122    # The port of the proxy server, if one is configured.
1123    def proxy_port
1124      if @proxy_from_env then
1125        proxy_uri&.port
1126      else
1127        @proxy_port
1128      end
1129    end
1130
1131    # [Bug #12921]
1132    if /linux|freebsd|darwin/ =~ RUBY_PLATFORM
1133      ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = true
1134    else
1135      ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = false
1136    end
1137
1138    # The username of the proxy server, if one is configured.
1139    def proxy_user
1140      if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1141        proxy_uri&.user
1142      else
1143        @proxy_user
1144      end
1145    end
1146
1147    # The password of the proxy server, if one is configured.
1148    def proxy_pass
1149      if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1150        proxy_uri&.password
1151      else
1152        @proxy_pass
1153      end
1154    end
1155
1156    alias proxyaddr proxy_address   #:nodoc: obsolete
1157    alias proxyport proxy_port      #:nodoc: obsolete
1158
1159    private
1160
1161    # without proxy, obsolete
1162
1163    def conn_address # :nodoc:
1164      address()
1165    end
1166
1167    def conn_port # :nodoc:
1168      port()
1169    end
1170
1171    def edit_path(path)
1172      if proxy?
1173        if path.start_with?("ftp://") || use_ssl?
1174          path
1175        else
1176          "http://#{addr_port}#{path}"
1177        end
1178      else
1179        path
1180      end
1181    end
1182
1183    #
1184    # HTTP operations
1185    #
1186
1187    public
1188
1189    # Retrieves data from +path+ on the connected-to host which may be an
1190    # absolute path String or a URI to extract the path from.
1191    #
1192    # +initheader+ must be a Hash like { 'Accept' => '*/*', ... },
1193    # and it defaults to an empty hash.
1194    # If +initheader+ doesn't have the key 'accept-encoding', then
1195    # a value of "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" is used,
1196    # so that gzip compression is used in preference to deflate
1197    # compression, which is used in preference to no compression.
1198    # Ruby doesn't have libraries to support the compress (Lempel-Ziv)
1199    # compression, so that is not supported.  The intent of this is
1200    # to reduce bandwidth by default.   If this routine sets up
1201    # compression, then it does the decompression also, removing
1202    # the header as well to prevent confusion.  Otherwise
1203    # it leaves the body as it found it.
1204    #
1205    # This method returns a Net::HTTPResponse object.
1206    #
1207    # If called with a block, yields each fragment of the
1208    # entity body in turn as a string as it is read from
1209    # the socket.  Note that in this case, the returned response
1210    # object will *not* contain a (meaningful) body.
1211    #
1212    # +dest+ argument is obsolete.
1213    # It still works but you must not use it.
1214    #
1215    # This method never raises an exception.
1216    #
1217    #     response = http.get('/index.html')
1218    #
1219    #     # using block
1220    #     File.open('result.txt', 'w') {|f|
1221    #       http.get('/~foo/') do |str|
1222    #         f.write str
1223    #       end
1224    #     }
1225    #
1226    def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+
1227      res = nil
1228      request(Get.new(path, initheader)) {|r|
1229        r.read_body dest, &block
1230        res = r
1231      }
1232      res
1233    end
1234
1235    # Gets only the header from +path+ on the connected-to host.
1236    # +header+ is a Hash like { 'Accept' => '*/*', ... }.
1237    #
1238    # This method returns a Net::HTTPResponse object.
1239    #
1240    # This method never raises an exception.
1241    #
1242    #     response = nil
1243    #     Net::HTTP.start('some.www.server', 80) {|http|
1244    #       response = http.head('/index.html')
1245    #     }
1246    #     p response['content-type']
1247    #
1248    def head(path, initheader = nil)
1249      request(Head.new(path, initheader))
1250    end
1251
1252    # Posts +data+ (must be a String) to +path+. +header+ must be a Hash
1253    # like { 'Accept' => '*/*', ... }.
1254    #
1255    # This method returns a Net::HTTPResponse object.
1256    #
1257    # If called with a block, yields each fragment of the
1258    # entity body in turn as a string as it is read from
1259    # the socket.  Note that in this case, the returned response
1260    # object will *not* contain a (meaningful) body.
1261    #
1262    # +dest+ argument is obsolete.
1263    # It still works but you must not use it.
1264    #
1265    # This method never raises exception.
1266    #
1267    #     response = http.post('/cgi-bin/search.rb', 'query=foo')
1268    #
1269    #     # using block
1270    #     File.open('result.txt', 'w') {|f|
1271    #       http.post('/cgi-bin/search.rb', 'query=foo') do |str|
1272    #         f.write str
1273    #       end
1274    #     }
1275    #
1276    # You should set Content-Type: header field for POST.
1277    # If no Content-Type: field given, this method uses
1278    # "application/x-www-form-urlencoded" by default.
1279    #
1280    def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
1281      send_entity(path, data, initheader, dest, Post, &block)
1282    end
1283
1284    # Sends a PATCH request to the +path+ and gets a response,
1285    # as an HTTPResponse object.
1286    def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
1287      send_entity(path, data, initheader, dest, Patch, &block)
1288    end
1289
1290    def put(path, data, initheader = nil)   #:nodoc:
1291      request(Put.new(path, initheader), data)
1292    end
1293
1294    # Sends a PROPPATCH request to the +path+ and gets a response,
1295    # as an HTTPResponse object.
1296    def proppatch(path, body, initheader = nil)
1297      request(Proppatch.new(path, initheader), body)
1298    end
1299
1300    # Sends a LOCK request to the +path+ and gets a response,
1301    # as an HTTPResponse object.
1302    def lock(path, body, initheader = nil)
1303      request(Lock.new(path, initheader), body)
1304    end
1305
1306    # Sends a UNLOCK request to the +path+ and gets a response,
1307    # as an HTTPResponse object.
1308    def unlock(path, body, initheader = nil)
1309      request(Unlock.new(path, initheader), body)
1310    end
1311
1312    # Sends a OPTIONS request to the +path+ and gets a response,
1313    # as an HTTPResponse object.
1314    def options(path, initheader = nil)
1315      request(Options.new(path, initheader))
1316    end
1317
1318    # Sends a PROPFIND request to the +path+ and gets a response,
1319    # as an HTTPResponse object.
1320    def propfind(path, body = nil, initheader = {'Depth' => '0'})
1321      request(Propfind.new(path, initheader), body)
1322    end
1323
1324    # Sends a DELETE request to the +path+ and gets a response,
1325    # as an HTTPResponse object.
1326    def delete(path, initheader = {'Depth' => 'Infinity'})
1327      request(Delete.new(path, initheader))
1328    end
1329
1330    # Sends a MOVE request to the +path+ and gets a response,
1331    # as an HTTPResponse object.
1332    def move(path, initheader = nil)
1333      request(Move.new(path, initheader))
1334    end
1335
1336    # Sends a COPY request to the +path+ and gets a response,
1337    # as an HTTPResponse object.
1338    def copy(path, initheader = nil)
1339      request(Copy.new(path, initheader))
1340    end
1341
1342    # Sends a MKCOL request to the +path+ and gets a response,
1343    # as an HTTPResponse object.
1344    def mkcol(path, body = nil, initheader = nil)
1345      request(Mkcol.new(path, initheader), body)
1346    end
1347
1348    # Sends a TRACE request to the +path+ and gets a response,
1349    # as an HTTPResponse object.
1350    def trace(path, initheader = nil)
1351      request(Trace.new(path, initheader))
1352    end
1353
1354    # Sends a GET request to the +path+.
1355    # Returns the response as a Net::HTTPResponse object.
1356    #
1357    # When called with a block, passes an HTTPResponse object to the block.
1358    # The body of the response will not have been read yet;
1359    # the block can process it using HTTPResponse#read_body,
1360    # if desired.
1361    #
1362    # Returns the response.
1363    #
1364    # This method never raises Net::* exceptions.
1365    #
1366    #     response = http.request_get('/index.html')
1367    #     # The entity body is already read in this case.
1368    #     p response['content-type']
1369    #     puts response.body
1370    #
1371    #     # Using a block
1372    #     http.request_get('/index.html') {|response|
1373    #       p response['content-type']
1374    #       response.read_body do |str|   # read body now
1375    #         print str
1376    #       end
1377    #     }
1378    #
1379    def request_get(path, initheader = nil, &block) # :yield: +response+
1380      request(Get.new(path, initheader), &block)
1381    end
1382
1383    # Sends a HEAD request to the +path+ and returns the response
1384    # as a Net::HTTPResponse object.
1385    #
1386    # Returns the response.
1387    #
1388    # This method never raises Net::* exceptions.
1389    #
1390    #     response = http.request_head('/index.html')
1391    #     p response['content-type']
1392    #
1393    def request_head(path, initheader = nil, &block)
1394      request(Head.new(path, initheader), &block)
1395    end
1396
1397    # Sends a POST request to the +path+.
1398    #
1399    # Returns the response as a Net::HTTPResponse object.
1400    #
1401    # When called with a block, the block is passed an HTTPResponse
1402    # object.  The body of that response will not have been read yet;
1403    # the block can process it using HTTPResponse#read_body, if desired.
1404    #
1405    # Returns the response.
1406    #
1407    # This method never raises Net::* exceptions.
1408    #
1409    #     # example
1410    #     response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
1411    #     p response.status
1412    #     puts response.body          # body is already read in this case
1413    #
1414    #     # using block
1415    #     http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
1416    #       p response.status
1417    #       p response['content-type']
1418    #       response.read_body do |str|   # read body now
1419    #         print str
1420    #       end
1421    #     }
1422    #
1423    def request_post(path, data, initheader = nil, &block) # :yield: +response+
1424      request Post.new(path, initheader), data, &block
1425    end
1426
1427    def request_put(path, data, initheader = nil, &block)   #:nodoc:
1428      request Put.new(path, initheader), data, &block
1429    end
1430
1431    alias get2   request_get    #:nodoc: obsolete
1432    alias head2  request_head   #:nodoc: obsolete
1433    alias post2  request_post   #:nodoc: obsolete
1434    alias put2   request_put    #:nodoc: obsolete
1435
1436
1437    # Sends an HTTP request to the HTTP server.
1438    # Also sends a DATA string if +data+ is given.
1439    #
1440    # Returns a Net::HTTPResponse object.
1441    #
1442    # This method never raises Net::* exceptions.
1443    #
1444    #    response = http.send_request('GET', '/index.html')
1445    #    puts response.body
1446    #
1447    def send_request(name, path, data = nil, header = nil)
1448      has_response_body = name != 'HEAD'
1449      r = HTTPGenericRequest.new(name,(data ? true : false),has_response_body,path,header)
1450      request r, data
1451    end
1452
1453    # Sends an HTTPRequest object +req+ to the HTTP server.
1454    #
1455    # If +req+ is a Net::HTTP::Post or Net::HTTP::Put request containing
1456    # data, the data is also sent. Providing data for a Net::HTTP::Head or
1457    # Net::HTTP::Get request results in an ArgumentError.
1458    #
1459    # Returns an HTTPResponse object.
1460    #
1461    # When called with a block, passes an HTTPResponse object to the block.
1462    # The body of the response will not have been read yet;
1463    # the block can process it using HTTPResponse#read_body,
1464    # if desired.
1465    #
1466    # This method never raises Net::* exceptions.
1467    #
1468    def request(req, body = nil, &block)  # :yield: +response+
1469      unless started?
1470        start {
1471          req['connection'] ||= 'close'
1472          return request(req, body, &block)
1473        }
1474      end
1475      if proxy_user()
1476        req.proxy_basic_auth proxy_user(), proxy_pass() unless use_ssl?
1477      end
1478      req.set_body_internal body
1479      res = transport_request(req, &block)
1480      if sspi_auth?(res)
1481        sspi_auth(req)
1482        res = transport_request(req, &block)
1483      end
1484      res
1485    end
1486
1487    private
1488
1489    # Executes a request which uses a representation
1490    # and returns its body.
1491    def send_entity(path, data, initheader, dest, type, &block)
1492      res = nil
1493      request(type.new(path, initheader), data) {|r|
1494        r.read_body dest, &block
1495        res = r
1496      }
1497      res
1498    end
1499
1500    IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc:
1501
1502    def transport_request(req)
1503      count = 0
1504      begin
1505        begin_transport req
1506        res = catch(:response) {
1507          req.exec @socket, @curr_http_version, edit_path(req.path)
1508          begin
1509            res = HTTPResponse.read_new(@socket)
1510            res.decode_content = req.decode_content
1511          end while res.kind_of?(HTTPInformation)
1512
1513          res.uri = req.uri
1514
1515          res
1516        }
1517        res.reading_body(@socket, req.response_body_permitted?) {
1518          yield res if block_given?
1519        }
1520      rescue Net::OpenTimeout
1521        raise
1522      rescue Net::ReadTimeout, IOError, EOFError,
1523             Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE,
1524             # avoid a dependency on OpenSSL
1525             defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError,
1526             Timeout::Error => exception
1527        if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method)
1528          count += 1
1529          @socket.close if @socket
1530          D "Conn close because of error #{exception}, and retry"
1531          retry
1532        end
1533        D "Conn close because of error #{exception}"
1534        @socket.close if @socket
1535        raise
1536      end
1537
1538      end_transport req, res
1539      res
1540    rescue => exception
1541      D "Conn close because of error #{exception}"
1542      @socket.close if @socket
1543      raise exception
1544    end
1545
1546    def begin_transport(req)
1547      if @socket.closed?
1548        connect
1549      elsif @last_communicated
1550        if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
1551          D 'Conn close because of keep_alive_timeout'
1552          @socket.close
1553          connect
1554        elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
1555          D "Conn close because of EOF"
1556          @socket.close
1557          connect
1558        end
1559      end
1560
1561      if not req.response_body_permitted? and @close_on_empty_response
1562        req['connection'] ||= 'close'
1563      end
1564
1565      req.update_uri address, port, use_ssl?
1566      req['host'] ||= addr_port()
1567    end
1568
1569    def end_transport(req, res)
1570      @curr_http_version = res.http_version
1571      @last_communicated = nil
1572      if @socket.closed?
1573        D 'Conn socket closed'
1574      elsif not res.body and @close_on_empty_response
1575        D 'Conn close'
1576        @socket.close
1577      elsif keep_alive?(req, res)
1578        D 'Conn keep-alive'
1579        @last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
1580      else
1581        D 'Conn close'
1582        @socket.close
1583      end
1584    end
1585
1586    def keep_alive?(req, res)
1587      return false if req.connection_close?
1588      if @curr_http_version <= '1.0'
1589        res.connection_keep_alive?
1590      else   # HTTP/1.1 or later
1591        not res.connection_close?
1592      end
1593    end
1594
1595    def sspi_auth?(res)
1596      return false unless @sspi_enabled
1597      if res.kind_of?(HTTPProxyAuthenticationRequired) and
1598          proxy? and res["Proxy-Authenticate"].include?("Negotiate")
1599        begin
1600          require 'win32/sspi'
1601          true
1602        rescue LoadError
1603          false
1604        end
1605      else
1606        false
1607      end
1608    end
1609
1610    def sspi_auth(req)
1611      n = Win32::SSPI::NegotiateAuth.new
1612      req["Proxy-Authorization"] = "Negotiate #{n.get_initial_token}"
1613      # Some versions of ISA will close the connection if this isn't present.
1614      req["Connection"] = "Keep-Alive"
1615      req["Proxy-Connection"] = "Keep-Alive"
1616      res = transport_request(req)
1617      authphrase = res["Proxy-Authenticate"]  or return res
1618      req["Proxy-Authorization"] = "Negotiate #{n.complete_authentication(authphrase)}"
1619    rescue => err
1620      raise HTTPAuthenticationError.new('HTTP authentication failed', err)
1621    end
1622
1623    #
1624    # utils
1625    #
1626
1627    private
1628
1629    def addr_port
1630      addr = address
1631      addr = "[#{addr}]" if addr.include?(":")
1632      default_port = use_ssl? ? HTTP.https_default_port : HTTP.http_default_port
1633      default_port == port ? addr : "#{addr}:#{port}"
1634    end
1635
1636    def D(msg)
1637      return unless @debug_output
1638      @debug_output << msg
1639      @debug_output << "\n"
1640    end
1641  end
1642
1643end
1644
1645require_relative 'http/exceptions'
1646
1647require_relative 'http/header'
1648
1649require_relative 'http/generic_request'
1650require_relative 'http/request'
1651require_relative 'http/requests'
1652
1653require_relative 'http/response'
1654require_relative 'http/responses'
1655
1656require_relative 'http/proxy_delta'
1657
1658require_relative 'http/backward'
1659