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