Updating tags for StringIO.
[rbx.git] / lib / net / http.rb
blob2dde75b7a4babe11440dcdb2927fe04cd834b66d
2 # = net/http.rb
4 # Copyright (c) 1999-2006 Yukihiro Matsumoto
5 # Copyright (c) 1999-2006 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>.
11 # This file is derived from "http-access.rb".
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.
19 # See Net::HTTP for an overview and examples. 
20
21 # NOTE: You can find Japanese version of this document here:
22 # http://www.ruby-lang.org/ja/man/?cmd=view;name=net%2Fhttp.rb
23
24 #--
25 # $Id: http.rb 11708 2007-02-12 23:01:19Z shyouhei $
26 #++ 
28 require 'net/protocol'
29 require 'uri'
31 module Net   #:nodoc:
33   # :stopdoc:
34   class HTTPBadResponse < StandardError; end
35   class HTTPHeaderSyntaxError < StandardError; end
36   # :startdoc:
38   # == What Is This Library?
39   # 
40   # This library provides your program functions to access WWW
41   # documents via HTTP, Hyper Text Transfer Protocol version 1.1.
42   # For details of HTTP, refer [RFC2616]
43   # (http://www.ietf.org/rfc/rfc2616.txt).
44   # 
45   # == Examples
46   # 
47   # === Getting Document From WWW Server
48   # 
49   # Example #1: Simple GET+print
50   # 
51   #     require 'net/http'
52   #     Net::HTTP.get_print 'www.example.com', '/index.html'
53   # 
54   # Example #2: Simple GET+print by URL
55   # 
56   #     require 'net/http'
57   #     require 'uri'
58   #     Net::HTTP.get_print URI.parse('http://www.example.com/index.html')
59   # 
60   # Example #3: More generic GET+print
61   # 
62   #     require 'net/http'
63   #     require 'uri'
64   #
65   #     url = URI.parse('http://www.example.com/index.html')
66   #     res = Net::HTTP.start(url.host, url.port) {|http|
67   #       http.get('/index.html')
68   #     }
69   #     puts res.body
70   #
71   # Example #4: More generic GET+print
72   # 
73   #     require 'net/http'
74   #
75   #     url = URI.parse('http://www.example.com/index.html')
76   #     req = Net::HTTP::Get.new(url.path)
77   #     res = Net::HTTP.start(url.host, url.port) {|http|
78   #       http.request(req)
79   #     }
80   #     puts res.body
81   # 
82   # === Posting Form Data
83   # 
84   #     require 'net/http'
85   #     require 'uri'
86   #
87   #     #1: Simple POST
88   #     res = Net::HTTP.post_form(URI.parse('http://www.example.com/search.cgi'),
89   #                               {'q'=>'ruby', 'max'=>'50'})
90   #     puts res.body
91   #
92   #     #2: POST with basic authentication
93   #     res = Net::HTTP.post_form(URI.parse('http://jack:pass@www.example.com/todo.cgi'),
94   #                                         {'from'=>'2005-01-01', 'to'=>'2005-03-31'})
95   #     puts res.body
96   #
97   #     #3: Detailed control
98   #     url = URI.parse('http://www.example.com/todo.cgi')
99   #     req = Net::HTTP::Post.new(url.path)
100   #     req.basic_auth 'jack', 'pass'
101   #     req.set_form_data({'from'=>'2005-01-01', 'to'=>'2005-03-31'}, ';')
102   #     res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
103   #     case res
104   #     when Net::HTTPSuccess, Net::HTTPRedirection
105   #       # OK
106   #     else
107   #       res.error!
108   #     end
109   # 
110   # === Accessing via Proxy
111   # 
112   # Net::HTTP.Proxy creates http proxy class. It has same
113   # methods of Net::HTTP but its instances always connect to
114   # proxy, instead of given host.
115   # 
116   #     require 'net/http'
117   # 
118   #     proxy_addr = 'your.proxy.host'
119   #     proxy_port = 8080
120   #             :
121   #     Net::HTTP::Proxy(proxy_addr, proxy_port).start('www.example.com') {|http|
122   #       # always connect to your.proxy.addr:8080
123   #             :
124   #     }
125   # 
126   # Since Net::HTTP.Proxy returns Net::HTTP itself when proxy_addr is nil,
127   # there's no need to change code if there's proxy or not.
128   # 
129   # There are two additional parameters in Net::HTTP.Proxy which allow to
130   # specify proxy user name and password:
131   # 
132   #     Net::HTTP::Proxy(proxy_addr, proxy_port, proxy_user = nil, proxy_pass = nil)
133   # 
134   # You may use them to work with authorization-enabled proxies:
135   # 
136   #     require 'net/http'
137   #     require 'uri'
138   #     
139   #     proxy_host = 'your.proxy.host'
140   #     proxy_port = 8080
141   #     uri = URI.parse(ENV['http_proxy'])
142   #     proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
143   #     Net::HTTP::Proxy(proxy_host, proxy_port,
144   #                      proxy_user, proxy_pass).start('www.example.com') {|http|
145   #       # always connect to your.proxy.addr:8080 using specified username and password
146   #             :
147   #     }
148   #
149   # Note that net/http never rely on HTTP_PROXY environment variable.
150   # If you want to use proxy, set it explicitly.
151   # 
152   # === Following Redirection
153   # 
154   #     require 'net/http'
155   #     require 'uri'
156   # 
157   #     def fetch(uri_str, limit = 10)
158   #       # You should choose better exception. 
159   #       raise ArgumentError, 'HTTP redirect too deep' if limit == 0
160   # 
161   #       response = Net::HTTP.get_response(URI.parse(uri_str))
162   #       case response
163   #       when Net::HTTPSuccess     then response
164   #       when Net::HTTPRedirection then fetch(response['location'], limit - 1)
165   #       else
166   #         response.error!
167   #       end
168   #     end
169   # 
170   #     print fetch('http://www.ruby-lang.org')
171   # 
172   # Net::HTTPSuccess and Net::HTTPRedirection is a HTTPResponse class.
173   # All HTTPResponse objects belong to its own response class which
174   # indicate HTTP result status. For details of response classes,
175   # see section "HTTP Response Classes".
176   # 
177   # === Basic Authentication
178   # 
179   #     require 'net/http'
180   # 
181   #     Net::HTTP.start('www.example.com') {|http|
182   #       req = Net::HTTP::Get.new('/secret-page.html')
183   #       req.basic_auth 'account', 'password'
184   #       response = http.request(req)
185   #       print response.body
186   #     }
187   # 
188   # === HTTP Request Classes
189   #
190   # Here is HTTP request class hierarchy.
191   #
192   #   Net::HTTPRequest
193   #       Net::HTTP::Get
194   #       Net::HTTP::Head
195   #       Net::HTTP::Post
196   #       Net::HTTP::Put
197   #       Net::HTTP::Proppatch
198   #       Net::HTTP::Lock
199   #       Net::HTTP::Unlock
200   #       Net::HTTP::Options
201   #       Net::HTTP::Propfind
202   #       Net::HTTP::Delete
203   #       Net::HTTP::Move
204   #       Net::HTTP::Copy
205   #       Net::HTTP::Mkcol
206   #       Net::HTTP::Trace
207   #
208   # === HTTP Response Classes
209   #
210   # Here is HTTP response class hierarchy.
211   # All classes are defined in Net module.
212   #
213   #   HTTPResponse
214   #       HTTPUnknownResponse
215   #       HTTPInformation                    # 1xx
216   #           HTTPContinue                       # 100
217   #           HTTPSwitchProtocl                  # 101
218   #       HTTPSuccess                        # 2xx
219   #           HTTPOK                             # 200
220   #           HTTPCreated                        # 201
221   #           HTTPAccepted                       # 202
222   #           HTTPNonAuthoritativeInformation    # 203
223   #           HTTPNoContent                      # 204
224   #           HTTPResetContent                   # 205
225   #           HTTPPartialContent                 # 206
226   #       HTTPRedirection                    # 3xx
227   #           HTTPMultipleChoice                 # 300
228   #           HTTPMovedPermanently               # 301
229   #           HTTPFound                          # 302
230   #           HTTPSeeOther                       # 303
231   #           HTTPNotModified                    # 304
232   #           HTTPUseProxy                       # 305
233   #           HTTPTemporaryRedirect              # 307
234   #       HTTPClientError                    # 4xx
235   #           HTTPBadRequest                     # 400
236   #           HTTPUnauthorized                   # 401
237   #           HTTPPaymentRequired                # 402
238   #           HTTPForbidden                      # 403
239   #           HTTPNotFound                       # 404
240   #           HTTPMethodNotAllowed               # 405
241   #           HTTPNotAcceptable                  # 406
242   #           HTTPProxyAuthenticationRequired    # 407
243   #           HTTPRequestTimeOut                 # 408
244   #           HTTPConflict                       # 409
245   #           HTTPGone                           # 410
246   #           HTTPLengthRequired                 # 411
247   #           HTTPPreconditionFailed             # 412
248   #           HTTPRequestEntityTooLarge          # 413
249   #           HTTPRequestURITooLong              # 414
250   #           HTTPUnsupportedMediaType           # 415
251   #           HTTPRequestedRangeNotSatisfiable   # 416
252   #           HTTPExpectationFailed              # 417
253   #       HTTPServerError                    # 5xx
254   #           HTTPInternalServerError            # 500
255   #           HTTPNotImplemented                 # 501
256   #           HTTPBadGateway                     # 502
257   #           HTTPServiceUnavailable             # 503
258   #           HTTPGatewayTimeOut                 # 504
259   #           HTTPVersionNotSupported            # 505
260   # 
261   # == Switching Net::HTTP versions
262   # 
263   # You can use net/http.rb 1.1 features (bundled with Ruby 1.6)
264   # by calling HTTP.version_1_1. Calling Net::HTTP.version_1_2
265   # allows you to use 1.2 features again.
266   # 
267   #     # example
268   #     Net::HTTP.start {|http1| ...(http1 has 1.2 features)... }
269   # 
270   #     Net::HTTP.version_1_1
271   #     Net::HTTP.start {|http2| ...(http2 has 1.1 features)... }
272   # 
273   #     Net::HTTP.version_1_2
274   #     Net::HTTP.start {|http3| ...(http3 has 1.2 features)... }
275   # 
276   # This function is NOT thread-safe.
277   #
278   class HTTP < Protocol
280     # :stopdoc:
281     Revision = %q$Revision: 11708 $.split[1]
282     HTTPVersion = '1.1'
283     @newimpl = true
284     # :startdoc:
286     # Turns on net/http 1.2 (ruby 1.8) features.
287     # Defaults to ON in ruby 1.8.
288     #
289     # I strongly recommend to call this method always.
290     #
291     #   require 'net/http'
292     #   Net::HTTP.version_1_2
293     #
294     def HTTP.version_1_2
295       @newimpl = true
296     end
298     # Turns on net/http 1.1 (ruby 1.6) features.
299     # Defaults to OFF in ruby 1.8.
300     def HTTP.version_1_1
301       @newimpl = false
302     end
304     # true if net/http is in version 1.2 mode.
305     # Defaults to true.
306     def HTTP.version_1_2?
307       @newimpl
308     end
310     # true if net/http is in version 1.1 compatible mode.
311     # Defaults to true.
312     def HTTP.version_1_1?
313       not @newimpl
314     end
316     class << HTTP
317       alias is_version_1_1? version_1_1?   #:nodoc:
318       alias is_version_1_2? version_1_2?   #:nodoc:
319     end
321     #
322     # short cut methods
323     #
325     #
326     # Get body from target and output it to +$stdout+.  The
327     # target can either be specified as (+uri+), or as
328     # (+host+, +path+, +port+ = 80); so: 
329     #
330     #    Net::HTTP.get_print URI.parse('http://www.example.com/index.html')
331     #
332     # or:
333     #
334     #    Net::HTTP.get_print 'www.example.com', '/index.html'
335     #
336     def HTTP.get_print(uri_or_host, path = nil, port = nil)
337       get_response(uri_or_host, path, port) {|res|
338         res.read_body do |chunk|
339           $stdout.print chunk
340         end
341       }
342       nil
343     end
345     # Send a GET request to the target and return the response
346     # as a string.  The target can either be specified as
347     # (+uri+), or as (+host+, +path+, +port+ = 80); so:
348     # 
349     #    print Net::HTTP.get(URI.parse('http://www.example.com/index.html'))
350     #
351     # or:
352     #
353     #    print Net::HTTP.get('www.example.com', '/index.html')
354     #
355     def HTTP.get(uri_or_host, path = nil, port = nil)
356       get_response(uri_or_host, path, port).body
357     end
359     # Send a GET request to the target and return the response
360     # as a Net::HTTPResponse object.  The target can either be specified as
361     # (+uri+), or as (+host+, +path+, +port+ = 80); so:
362     # 
363     #    res = Net::HTTP.get_response(URI.parse('http://www.example.com/index.html'))
364     #    print res.body
365     #
366     # or:
367     #
368     #    res = Net::HTTP.get_response('www.example.com', '/index.html')
369     #    print res.body
370     #
371     def HTTP.get_response(uri_or_host, path = nil, port = nil, &block)
372       if path
373         host = uri_or_host
374         new(host, port || HTTP.default_port).start {|http|
375           return http.request_get(path, &block)
376         }
377       else
378         uri = uri_or_host
379         new(uri.host, uri.port).start {|http|
380           return http.request_get(uri.request_uri, &block)
381         }
382       end
383     end
385     # Posts HTML form data to the +URL+.
386     # Form data must be represented as a Hash of String to String, e.g:
387     #
388     #   { "cmd" => "search", "q" => "ruby", "max" => "50" }
389     #
390     # This method also does Basic Authentication iff +URL+.user exists.
391     #
392     # Example:
393     #
394     #   require 'net/http'
395     #   require 'uri'
396     #
397     #   HTTP.post_form URI.parse('http://www.example.com/search.cgi'),
398     #                  { "q" => "ruby", "max" => "50" }
399     #
400     def HTTP.post_form(url, params)
401       req = Post.new(url.path)
402       req.form_data = params
403       req.basic_auth url.user, url.password if url.user
404       new(url.host, url.port).start {|http|
405         http.request(req)
406       }
407     end
409     #
410     # HTTP session management
411     #
413     # The default port to use for HTTP requests; defaults to 80.
414     def HTTP.default_port
415       http_default_port()
416     end
418     # The default port to use for HTTP requests; defaults to 80.
419     def HTTP.http_default_port
420       80
421     end
423     # The default port to use for HTTPS requests; defaults to 443.
424     def HTTP.https_default_port
425       443
426     end
428     def HTTP.socket_type   #:nodoc: obsolete
429       BufferedIO
430     end
432     # creates a new Net::HTTP object and opens its TCP connection and 
433     # HTTP session.  If the optional block is given, the newly 
434     # created Net::HTTP object is passed to it and closed when the 
435     # block finishes.  In this case, the return value of this method
436     # is the return value of the block.  If no block is given, the
437     # return value of this method is the newly created Net::HTTP object
438     # itself, and the caller is responsible for closing it upon completion.
439     def HTTP.start(address, port = nil, p_addr = nil, p_port = nil, p_user = nil, p_pass = nil, &block) # :yield: +http+
440       new(address, port, p_addr, p_port, p_user, p_pass).start(&block)
441     end
443     class << HTTP
444       alias newobj new
445     end
447     # Creates a new Net::HTTP object.
448     # If +proxy_addr+ is given, creates an Net::HTTP object with proxy support.
449     # This method does not open the TCP connection.
450     def HTTP.new(address, port = nil, p_addr = nil, p_port = nil, p_user = nil, p_pass = nil)
451       h = Proxy(p_addr, p_port, p_user, p_pass).newobj(address, port)
452       h.instance_eval {
453         @newimpl = ::Net::HTTP.version_1_2?
454       }
455       h
456     end
458     # Creates a new Net::HTTP object for the specified +address+.
459     # This method does not open the TCP connection.
460     def initialize(address, port = nil)
461       @address = address
462       @port    = (port || HTTP.default_port)
463       @curr_http_version = HTTPVersion
464       @seems_1_0_server = false
465       @close_on_empty_response = false
466       @socket  = nil
467       @started = false
468       @open_timeout = nil
469       @read_timeout = 60
470       @debug_output = nil
471       @use_ssl = false
472       @ssl_context = nil
473     end
475     def inspect
476       "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
477     end
479     # *WARNING* This method causes serious security hole.
480     # Never use this method in production code.
481     #
482     # Set an output stream for debugging.
483     #
484     #   http = Net::HTTP.new
485     #   http.set_debug_output $stderr
486     #   http.start { .... }
487     #
488     def set_debug_output(output)
489       warn 'Net::HTTP#set_debug_output called after HTTP started' if started?
490       @debug_output = output
491     end
493     # The host name to connect to.
494     attr_reader :address
496     # The port number to connect to.
497     attr_reader :port
499     # Seconds to wait until connection is opened.
500     # If the HTTP object cannot open a connection in this many seconds,
501     # it raises a TimeoutError exception.
502     attr_accessor :open_timeout
504     # Seconds to wait until reading one block (by one read(2) call).
505     # If the HTTP object cannot open a connection in this many seconds,
506     # it raises a TimeoutError exception.
507     attr_reader :read_timeout
509     # Setter for the read_timeout attribute.
510     def read_timeout=(sec)
511       @socket.read_timeout = sec if @socket
512       @read_timeout = sec
513     end
515     # returns true if the HTTP session is started.
516     def started?
517       @started
518     end
520     alias active? started?   #:nodoc: obsolete
522     attr_accessor :close_on_empty_response
524     # returns true if use SSL/TLS with HTTP.
525     def use_ssl?
526       false   # redefined in net/https
527     end
529     # Opens TCP connection and HTTP session.
530     # 
531     # When this method is called with block, gives a HTTP object
532     # to the block and closes the TCP connection / HTTP session
533     # after the block executed.
534     #
535     # When called with a block, returns the return value of the
536     # block; otherwise, returns self.
537     #
538     def start  # :yield: http
539       raise IOError, 'HTTP session already opened' if @started
540       if block_given?
541         begin
542           do_start
543           return yield(self)
544         ensure
545           do_finish
546         end
547       end
548       do_start
549       self
550     end
552     def do_start
553       connect
554       @started = true
555     end
556     private :do_start
558     def connect
559       D "opening connection to #{conn_address()}..."
560       s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
561       D "opened"
562       if use_ssl?
563         unless @ssl_context.verify_mode
564           warn "warning: peer certificate won't be verified in this SSL session"
565           @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
566         end
567         s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
568         s.sync_close = true
569       end
570       @socket = BufferedIO.new(s)
571       @socket.read_timeout = @read_timeout
572       @socket.debug_output = @debug_output
573       if use_ssl?
574         if proxy?
575           @socket.writeline sprintf('CONNECT %s:%s HTTP/%s',
576                                     @address, @port, HTTPVersion)
577           @socket.writeline "Host: #{@address}:#{@port}"
578           if proxy_user
579             credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
580             credential.delete!("\r\n")
581             @socket.writeline "Proxy-Authorization: Basic #{credential}"
582           end
583           @socket.writeline ''
584           HTTPResponse.read_new(@socket).value
585         end
586         s.connect
587       end
588       on_connect
589     end
590     private :connect
592     def on_connect
593     end
594     private :on_connect
596     # Finishes HTTP session and closes TCP connection.
597     # Raises IOError if not started.
598     def finish
599       raise IOError, 'HTTP session not yet started' unless started?
600       do_finish
601     end
603     def do_finish
604       @started = false
605       @socket.close if @socket and not @socket.closed?
606       @socket = nil
607     end
608     private :do_finish
610     #
611     # proxy
612     #
614     public
616     # no proxy
617     @is_proxy_class = false
618     @proxy_addr = nil
619     @proxy_port = nil
620     @proxy_user = nil
621     @proxy_pass = nil
623     # Creates an HTTP proxy class.
624     # Arguments are address/port of proxy host and username/password
625     # if authorization on proxy server is required.
626     # You can replace the HTTP class with created proxy class.
627     # 
628     # If ADDRESS is nil, this method returns self (Net::HTTP).
629     # 
630     #     # Example
631     #     proxy_class = Net::HTTP::Proxy('proxy.example.com', 8080)
632     #                     :
633     #     proxy_class.start('www.ruby-lang.org') {|http|
634     #       # connecting proxy.foo.org:8080
635     #                     :
636     #     }
637     # 
638     def HTTP.Proxy(p_addr, p_port = nil, p_user = nil, p_pass = nil)
639       return self unless p_addr
640       delta = ProxyDelta
641       proxyclass = Class.new(self)
642       proxyclass.module_eval {
643         include delta
644         # with proxy
645         @is_proxy_class = true
646         @proxy_address = p_addr
647         @proxy_port    = p_port || default_port()
648         @proxy_user    = p_user
649         @proxy_pass    = p_pass
650       }
651       proxyclass
652     end
654     class << HTTP
655       # returns true if self is a class which was created by HTTP::Proxy.
656       def proxy_class?
657         @is_proxy_class
658       end
660       attr_reader :proxy_address
661       attr_reader :proxy_port
662       attr_reader :proxy_user
663       attr_reader :proxy_pass
664     end
666     # True if self is a HTTP proxy class.
667     def proxy?
668       self.class.proxy_class?
669     end
671     # Address of proxy host. If self does not use a proxy, nil.
672     def proxy_address
673       self.class.proxy_address
674     end
676     # Port number of proxy host. If self does not use a proxy, nil.
677     def proxy_port
678       self.class.proxy_port
679     end
681     # User name for accessing proxy. If self does not use a proxy, nil.
682     def proxy_user
683       self.class.proxy_user
684     end
686     # User password for accessing proxy. If self does not use a proxy, nil.
687     def proxy_pass
688       self.class.proxy_pass
689     end
691     alias proxyaddr proxy_address   #:nodoc: obsolete
692     alias proxyport proxy_port      #:nodoc: obsolete
694     private
696     # without proxy
698     def conn_address
699       address()
700     end
702     def conn_port
703       port()
704     end
706     def edit_path(path)
707       path
708     end
710     module ProxyDelta   #:nodoc: internal use only
711       private
713       def conn_address
714         proxy_address()
715       end
717       def conn_port
718         proxy_port()
719       end
721       def edit_path(path)
722         use_ssl? ? path : "http://#{addr_port()}#{path}"
723       end
724     end
726     #
727     # HTTP operations
728     #
730     public
732     # Gets data from +path+ on the connected-to host.
733     # +header+ must be a Hash like { 'Accept' => '*/*', ... }.
734     #
735     # In version 1.1 (ruby 1.6), this method returns a pair of objects,
736     # a Net::HTTPResponse object and the entity body string.
737     # In version 1.2 (ruby 1.8), this method returns a Net::HTTPResponse
738     # object.
739     #
740     # If called with a block, yields each fragment of the
741     # entity body in turn as a string as it is read from
742     # the socket.  Note that in this case, the returned response
743     # object will *not* contain a (meaningful) body.
744     #
745     # +dest+ argument is obsolete.
746     # It still works but you must not use it.
747     #
748     # In version 1.1, this method might raise an exception for 
749     # 3xx (redirect). In this case you can get a HTTPResponse object
750     # by "anException.response".
751     #
752     # In version 1.2, this method never raises exception.
753     #
754     #     # version 1.1 (bundled with Ruby 1.6)
755     #     response, body = http.get('/index.html')
756     #
757     #     # version 1.2 (bundled with Ruby 1.8 or later)
758     #     response = http.get('/index.html')
759     #     
760     #     # using block
761     #     File.open('result.txt', 'w') {|f|
762     #       http.get('/~foo/') do |str|
763     #         f.write str
764     #       end
765     #     }
766     #
767     def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+
768       res = nil
769       request(Get.new(path, initheader)) {|r|
770         r.read_body dest, &block
771         res = r
772       }
773       unless @newimpl
774         res.value
775         return res, res.body
776       end
778       res
779     end
781     # Gets only the header from +path+ on the connected-to host.
782     # +header+ is a Hash like { 'Accept' => '*/*', ... }.
783     # 
784     # This method returns a Net::HTTPResponse object.
785     # 
786     # In version 1.1, this method might raise an exception for 
787     # 3xx (redirect). On the case you can get a HTTPResponse object
788     # by "anException.response".
789     # In version 1.2, this method never raises an exception.
790     # 
791     #     response = nil
792     #     Net::HTTP.start('some.www.server', 80) {|http|
793     #       response = http.head('/index.html')
794     #     }
795     #     p response['content-type']
796     #
797     def head(path, initheader = nil) 
798       res = request(Head.new(path, initheader))
799       res.value unless @newimpl
800       res
801     end
803     # Posts +data+ (must be a String) to +path+. +header+ must be a Hash
804     # like { 'Accept' => '*/*', ... }.
805     # 
806     # In version 1.1 (ruby 1.6), this method returns a pair of objects, a
807     # Net::HTTPResponse object and an entity body string.
808     # In version 1.2 (ruby 1.8), this method returns a Net::HTTPResponse object.
809     # 
810     # If called with a block, yields each fragment of the
811     # entity body in turn as a string as it are read from
812     # the socket.  Note that in this case, the returned response
813     # object will *not* contain a (meaningful) body.
814     #
815     # +dest+ argument is obsolete.
816     # It still works but you must not use it.
817     # 
818     # In version 1.1, this method might raise an exception for 
819     # 3xx (redirect). In this case you can get an HTTPResponse object
820     # by "anException.response".
821     # In version 1.2, this method never raises exception.
822     # 
823     #     # version 1.1
824     #     response, body = http.post('/cgi-bin/search.rb', 'query=foo')
825     # 
826     #     # version 1.2
827     #     response = http.post('/cgi-bin/search.rb', 'query=foo')
828     # 
829     #     # using block
830     #     File.open('result.txt', 'w') {|f|
831     #       http.post('/cgi-bin/search.rb', 'query=foo') do |str|
832     #         f.write str
833     #       end
834     #     }
835     #
836     # You should set Content-Type: header field for POST.
837     # If no Content-Type: field given, this method uses
838     # "application/x-www-form-urlencoded" by default.
839     #
840     def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
841       res = nil
842       request(Post.new(path, initheader), data) {|r|
843         r.read_body dest, &block
844         res = r
845       }
846       unless @newimpl
847         res.value
848         return res, res.body
849       end
850       res
851     end
853     def put(path, data, initheader = nil)   #:nodoc:
854       res = request(Put.new(path, initheader), data)
855       res.value unless @newimpl
856       res
857     end
859     # Sends a PROPPATCH request to the +path+ and gets a response,
860     # as an HTTPResponse object.
861     def proppatch(path, body, initheader = nil)
862       request(Proppatch.new(path, initheader), body)
863     end
865     # Sends a LOCK request to the +path+ and gets a response,
866     # as an HTTPResponse object.
867     def lock(path, body, initheader = nil)
868       request(Lock.new(path, initheader), body)
869     end
871     # Sends a UNLOCK request to the +path+ and gets a response,
872     # as an HTTPResponse object.
873     def unlock(path, body, initheader = nil)
874       request(Unlock.new(path, initheader), body)
875     end
877     # Sends a OPTIONS request to the +path+ and gets a response,
878     # as an HTTPResponse object.
879     def options(path, initheader = nil)
880       request(Options.new(path, initheader))
881     end
883     # Sends a PROPFIND request to the +path+ and gets a response,
884     # as an HTTPResponse object.
885     def propfind(path, body = nil, initheader = {'Depth' => '0'})
886       request(Propfind.new(path, initheader), body)
887     end
889     # Sends a DELETE request to the +path+ and gets a response,
890     # as an HTTPResponse object.
891     def delete(path, initheader = {'Depth' => 'Infinity'})
892       request(Delete.new(path, initheader))
893     end
895     # Sends a MOVE request to the +path+ and gets a response,
896     # as an HTTPResponse object.
897     def move(path, initheader = nil)
898       request(Move.new(path, initheader))
899     end
901     # Sends a COPY request to the +path+ and gets a response,
902     # as an HTTPResponse object.
903     def copy(path, initheader = nil)
904       request(Copy.new(path, initheader))
905     end
907     # Sends a MKCOL request to the +path+ and gets a response,
908     # as an HTTPResponse object.
909     def mkcol(path, body = nil, initheader = nil)
910       request(Mkcol.new(path, initheader), body)
911     end
913     # Sends a TRACE request to the +path+ and gets a response,
914     # as an HTTPResponse object.
915     def trace(path, initheader = nil)
916       request(Trace.new(path, initheader))
917     end
919     # Sends a GET request to the +path+ and gets a response,
920     # as an HTTPResponse object.
921     # 
922     # When called with a block, yields an HTTPResponse object.
923     # The body of this response will not have been read yet;
924     # the caller can process it using HTTPResponse#read_body,
925     # if desired.
926     #
927     # Returns the response.
928     # 
929     # This method never raises Net::* exceptions.
930     # 
931     #     response = http.request_get('/index.html')
932     #     # The entity body is already read here.
933     #     p response['content-type']
934     #     puts response.body
935     # 
936     #     # using block
937     #     http.request_get('/index.html') {|response|
938     #       p response['content-type']
939     #       response.read_body do |str|   # read body now
940     #         print str
941     #       end
942     #     }
943     #
944     def request_get(path, initheader = nil, &block) # :yield: +response+
945       request(Get.new(path, initheader), &block)
946     end
948     # Sends a HEAD request to the +path+ and gets a response,
949     # as an HTTPResponse object.
950     #
951     # Returns the response.
952     # 
953     # This method never raises Net::* exceptions.
954     # 
955     #     response = http.request_head('/index.html')
956     #     p response['content-type']
957     #
958     def request_head(path, initheader = nil, &block)
959       request(Head.new(path, initheader), &block)
960     end
962     # Sends a POST request to the +path+ and gets a response,
963     # as an HTTPResponse object.
964     # 
965     # When called with a block, yields an HTTPResponse object.
966     # The body of this response will not have been read yet;
967     # the caller can process it using HTTPResponse#read_body,
968     # if desired.
969     #
970     # Returns the response.
971     # 
972     # This method never raises Net::* exceptions.
973     # 
974     #     # example
975     #     response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
976     #     p response.status
977     #     puts response.body          # body is already read
978     # 
979     #     # using block
980     #     http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
981     #       p response.status
982     #       p response['content-type']
983     #       response.read_body do |str|   # read body now
984     #         print str
985     #       end
986     #     }
987     #
988     def request_post(path, data, initheader = nil, &block) # :yield: +response+
989       request Post.new(path, initheader), data, &block
990     end
992     def request_put(path, data, initheader = nil, &block)   #:nodoc:
993       request Put.new(path, initheader), data, &block
994     end
996     alias get2   request_get    #:nodoc: obsolete
997     alias head2  request_head   #:nodoc: obsolete
998     alias post2  request_post   #:nodoc: obsolete
999     alias put2   request_put    #:nodoc: obsolete
1002     # Sends an HTTP request to the HTTP server.
1003     # This method also sends DATA string if DATA is given.
1004     #
1005     # Returns a HTTPResponse object.
1006     # 
1007     # This method never raises Net::* exceptions.
1008     #
1009     #    response = http.send_request('GET', '/index.html')
1010     #    puts response.body
1011     #
1012     def send_request(name, path, data = nil, header = nil)
1013       r = HTTPGenericRequest.new(name,(data ? true : false),true,path,header)
1014       request r, data
1015     end
1017     # Sends an HTTPRequest object REQUEST to the HTTP server.
1018     # This method also sends DATA string if REQUEST is a post/put request.
1019     # Giving DATA for get/head request causes ArgumentError.
1020     # 
1021     # When called with a block, yields an HTTPResponse object.
1022     # The body of this response will not have been read yet;
1023     # the caller can process it using HTTPResponse#read_body,
1024     # if desired.
1025     #
1026     # Returns a HTTPResponse object.
1027     # 
1028     # This method never raises Net::* exceptions.
1029     #
1030     def request(req, body = nil, &block)  # :yield: +response+
1031       unless started?
1032         start {
1033           req['connection'] ||= 'close'
1034           return request(req, body, &block)
1035         }
1036       end
1037       if proxy_user()
1038         unless use_ssl?
1039           req.proxy_basic_auth proxy_user(), proxy_pass()
1040         end
1041       end
1043       req.set_body_internal body
1044       begin_transport req
1045         req.exec @socket, @curr_http_version, edit_path(req.path)
1046         begin
1047           res = HTTPResponse.read_new(@socket)
1048         end while res.kind_of?(HTTPContinue)
1049         res.reading_body(@socket, req.response_body_permitted?) {
1050           yield res if block_given?
1051         }
1052       end_transport req, res
1054       res
1055     end
1057     private
1059     def begin_transport(req)
1060       if @socket.closed?
1061         connect
1062       end
1063       if @seems_1_0_server
1064         req['connection'] ||= 'close'
1065       end
1066       if not req.response_body_permitted? and @close_on_empty_response
1067         req['connection'] ||= 'close'
1068       end
1069       req['host'] ||= addr_port()
1070     end
1072     def end_transport(req, res)
1073       @curr_http_version = res.http_version
1074       if not res.body and @close_on_empty_response
1075         D 'Conn close'
1076         @socket.close
1077       elsif keep_alive?(req, res)
1078         D 'Conn keep-alive'
1079         if @socket.closed?
1080           D 'Conn (but seems 1.0 server)'
1081           @seems_1_0_server = true
1082         end
1083       else
1084         D 'Conn close'
1085         @socket.close
1086       end
1087     end
1089     def keep_alive?(req, res)
1090       return false if /close/i =~ req['connection'].to_s
1091       return false if @seems_1_0_server
1092       return true  if /keep-alive/i =~ res['connection'].to_s
1093       return false if /close/i      =~ res['connection'].to_s
1094       return true  if /keep-alive/i =~ res['proxy-connection'].to_s
1095       return false if /close/i      =~ res['proxy-connection'].to_s
1096       (@curr_http_version == '1.1')
1097     end
1099     #
1100     # utils
1101     #
1103     private
1105     def addr_port
1106       if use_ssl?
1107         address() + (port == HTTP.https_default_port ? '' : ":#{port()}")
1108       else
1109         address() + (port == HTTP.http_default_port ? '' : ":#{port()}")
1110       end
1111     end
1113     def D(msg)
1114       return unless @debug_output
1115       @debug_output << msg
1116       @debug_output << "\n"
1117     end
1119   end
1121   HTTPSession = HTTP
1124   #
1125   # Header module.
1126   #
1127   # Provides access to @header in the mixed-into class as a hash-like
1128   # object, except with case-insensitive keys.  Also provides
1129   # methods for accessing commonly-used header values in a more
1130   # convenient format.
1131   #
1132   module HTTPHeader
1134     def initialize_http_header(initheader)
1135       @header = {}
1136       return unless initheader
1137       initheader.each do |key, value|
1138         warn "net/http: warning: duplicated HTTP header: #{key}" if key?(key) and $VERBOSE
1139         @header[key.downcase] = [value.strip]
1140       end
1141     end
1143     def size   #:nodoc: obsolete
1144       @header.size
1145     end
1147     alias length size   #:nodoc: obsolete
1149     # Returns the header field corresponding to the case-insensitive key.
1150     # For example, a key of "Content-Type" might return "text/html"
1151     def [](key)
1152       a = @header[key.downcase] or return nil
1153       a.join(', ')
1154     end
1156     # Sets the header field corresponding to the case-insensitive key.
1157     def []=(key, val)
1158       unless val
1159         @header.delete key.downcase
1160         return val
1161       end
1162       @header[key.downcase] = [val]
1163     end
1165     # [Ruby 1.8.3]
1166     # Adds header field instead of replace.
1167     # Second argument +val+ must be a String.
1168     # See also #[]=, #[] and #get_fields.
1169     #
1170     #   request.add_field 'X-My-Header', 'a'
1171     #   p request['X-My-Header']              #=> "a"
1172     #   p request.get_fields('X-My-Header')   #=> ["a"]
1173     #   request.add_field 'X-My-Header', 'b'
1174     #   p request['X-My-Header']              #=> "a, b"
1175     #   p request.get_fields('X-My-Header')   #=> ["a", "b"]
1176     #   request.add_field 'X-My-Header', 'c'
1177     #   p request['X-My-Header']              #=> "a, b, c"
1178     #   p request.get_fields('X-My-Header')   #=> ["a", "b", "c"]
1179     #
1180     def add_field(key, val)
1181       if @header.key?(key.downcase)
1182         @header[key.downcase].push val
1183       else
1184         @header[key.downcase] = [val]
1185       end
1186     end
1188     # [Ruby 1.8.3]
1189     # Returns an array of header field strings corresponding to the
1190     # case-insensitive +key+.  This method allows you to get duplicated
1191     # header fields without any processing.  See also #[].
1192     #
1193     #   p response.get_fields('Set-Cookie')
1194     #     #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23",
1195     #          "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"]
1196     #   p response['Set-Cookie']
1197     #     #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"
1198     #
1199     def get_fields(key)
1200       return nil unless @header[key.downcase]
1201       @header[key.downcase].dup
1202     end
1204     # Returns the header field corresponding to the case-insensitive key.
1205     # Returns the default value +args+, or the result of the block, or nil,
1206     # if there's no header field named key.  See Hash#fetch
1207     def fetch(key, *args, &block)   #:yield: +key+
1208       a = @header.fetch(key.downcase, *args, &block)
1209       a.join(', ')
1210     end
1212     # Iterates for each header names and values.
1213     def each_header   #:yield: +key+, +value+
1214       @header.each do |k,va|
1215         yield k, va.join(', ')
1216       end
1217     end
1219     alias each each_header
1221     # Iterates for each header names.
1222     def each_name(&block)   #:yield: +key+
1223       @header.each_key(&block)
1224     end
1226     alias each_key each_name
1228     # Iterates for each capitalized header names.
1229     def each_capitalized_name(&block)   #:yield: +key+
1230       @header.each_key do |k|
1231         yield capitalize(k)
1232       end
1233     end
1235     # Iterates for each header values.
1236     def each_value   #:yield: +value+
1237       @header.each_value do |va|
1238         yield va.join(', ')
1239       end
1240     end
1242     # Removes a header field.
1243     def delete(key)
1244       @header.delete(key.downcase)
1245     end
1247     # true if +key+ header exists.
1248     def key?(key)
1249       @header.key?(key.downcase)
1250     end
1252     # Returns a Hash consist of header names and values.
1253     def to_hash
1254       @header.dup
1255     end
1257     # As for #each_header, except the keys are provided in capitalized form.
1258     def each_capitalized
1259       @header.each do |k,v|
1260         yield capitalize(k), v.join(', ')
1261       end
1262     end
1264     alias canonical_each each_capitalized
1266     def capitalize(name)
1267       name.split(/-/).map {|s| s.capitalize }.join('-')
1268     end
1269     private :capitalize
1271     # Returns an Array of Range objects which represents Range: header field,
1272     # or +nil+ if there is no such header.
1273     def range
1274       return nil unless @header['range']
1275       self['Range'].split(/,/).map {|spec|
1276         m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match(spec) or
1277                 raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
1278         d1 = m[1].to_i
1279         d2 = m[2].to_i
1280         if    m[1] and m[2] then  d1..d2
1281         elsif m[1]          then  d1..-1
1282         elsif          m[2] then -d2..-1
1283         else
1284           raise HTTPHeaderSyntaxError, 'range is not specified'
1285         end
1286       }
1287     end
1289     # Set Range: header from Range (arg r) or beginning index and
1290     # length from it (arg idx&len).
1291     #
1292     #   req.range = (0..1023)
1293     #   req.set_range 0, 1023
1294     #
1295     def set_range(r, e = nil)
1296       unless r
1297         @header.delete 'range'
1298         return r
1299       end
1300       r = (r...r+e) if e
1301       case r
1302       when Numeric
1303         n = r.to_i
1304         rangestr = (n > 0 ? "0-#{n-1}" : "-#{-n}")
1305       when Range
1306         first = r.first
1307         last = r.last
1308         last -= 1 if r.exclude_end?
1309         if last == -1
1310           rangestr = (first > 0 ? "#{first}-" : "-#{-first}")
1311         else
1312           raise HTTPHeaderSyntaxError, 'range.first is negative' if first < 0
1313           raise HTTPHeaderSyntaxError, 'range.last is negative' if last < 0
1314           raise HTTPHeaderSyntaxError, 'must be .first < .last' if first > last
1315           rangestr = "#{first}-#{last}"
1316         end
1317       else
1318         raise TypeError, 'Range/Integer is required'
1319       end
1320       @header['range'] = ["bytes=#{rangestr}"]
1321       r
1322     end
1324     alias range= set_range
1326     # Returns an Integer object which represents the Content-Length: header field
1327     # or +nil+ if that field is not provided.
1328     def content_length
1329       return nil unless key?('Content-Length')
1330       len = self['Content-Length'].slice(/\d+/) or
1331           raise HTTPHeaderSyntaxError, 'wrong Content-Length format'
1332       len.to_i
1333     end
1334     
1335     def content_length=(len)
1336       unless len
1337         @header.delete 'content-length'
1338         return nil
1339       end
1340       @header['content-length'] = [len.to_i.to_s]
1341     end
1343     # Returns "true" if the "transfer-encoding" header is present and
1344     # set to "chunked".  This is an HTTP/1.1 feature, allowing the 
1345     # the content to be sent in "chunks" without at the outset
1346     # stating the entire content length.
1347     def chunked?
1348       return false unless @header['transfer-encoding']
1349       field = self['Transfer-Encoding']
1350       (/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false
1351     end
1353     # Returns a Range object which represents Content-Range: header field.
1354     # This indicates, for a partial entity body, where this fragment
1355     # fits inside the full entity body, as range of byte offsets.
1356     def content_range
1357       return nil unless @header['content-range']
1358       m = %r<bytes\s+(\d+)-(\d+)/(\d+|\*)>i.match(self['Content-Range']) or
1359           raise HTTPHeaderSyntaxError, 'wrong Content-Range format'
1360       m[1].to_i .. m[2].to_i + 1
1361     end
1363     # The length of the range represented in Content-Range: header.
1364     def range_length
1365       r = content_range() or return nil
1366       r.end - r.begin
1367     end
1369     # Returns a content type string such as "text/html".
1370     # This method returns nil if Content-Type: header field does not exist.
1371     def content_type
1372       return nil unless main_type()
1373       if sub_type()
1374       then "#{main_type()}/#{sub_type()}"
1375       else main_type()
1376       end
1377     end
1379     # Returns a content type string such as "text".
1380     # This method returns nil if Content-Type: header field does not exist.
1381     def main_type
1382       return nil unless @header['content-type']
1383       self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip
1384     end
1385     
1386     # Returns a content type string such as "html".
1387     # This method returns nil if Content-Type: header field does not exist
1388     # or sub-type is not given (e.g. "Content-Type: text").
1389     def sub_type
1390       return nil unless @header['content-type']
1391       main, sub = *self['Content-Type'].split(';').first.to_s.split('/')
1392       return nil unless sub
1393       sub.strip
1394     end
1396     # Returns content type parameters as a Hash as like
1397     # {"charset" => "iso-2022-jp"}.
1398     def type_params
1399       result = {}
1400       list = self['Content-Type'].to_s.split(';')
1401       list.shift
1402       list.each do |param|
1403         k, v = *param.split('=', 2)
1404         result[k.strip] = v.strip
1405       end
1406       result
1407     end
1409     # Set Content-Type: header field by +type+ and +params+.
1410     # +type+ must be a String, +params+ must be a Hash.
1411     def set_content_type(type, params = {})
1412       @header['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')]
1413     end
1415     alias content_type= set_content_type
1417     # Set header fields and a body from HTML form data.
1418     # +params+ should be a Hash containing HTML form data.
1419     # Optional argument +sep+ means data record separator.
1420     #
1421     # This method also set Content-Type: header field to
1422     # application/x-www-form-urlencoded.
1423     def set_form_data(params, sep = '&')
1424       self.body = params.map {|k,v| "#{urlencode(k.to_s)}=#{urlencode(v.to_s)}" }.join(sep)
1425       self.content_type = 'application/x-www-form-urlencoded'
1426     end
1428     alias form_data= set_form_data
1430     def urlencode(str)
1431       str.gsub(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0]) }
1432     end
1433     private :urlencode
1435     # Set the Authorization: header for "Basic" authorization.
1436     def basic_auth(account, password)
1437       @header['authorization'] = [basic_encode(account, password)]
1438     end
1440     # Set Proxy-Authorization: header for "Basic" authorization.
1441     def proxy_basic_auth(account, password)
1442       @header['proxy-authorization'] = [basic_encode(account, password)]
1443     end
1445     def basic_encode(account, password)
1446       'Basic ' + ["#{account}:#{password}"].pack('m').delete("\r\n")
1447     end
1448     private :basic_encode
1450   end
1453   #
1454   # Parent of HTTPRequest class.  Do not use this directly; use
1455   # a subclass of HTTPRequest.
1456   #
1457   # Mixes in the HTTPHeader module.
1458   #
1459   class HTTPGenericRequest
1461     include HTTPHeader
1463     def initialize(m, reqbody, resbody, path, initheader = nil)
1464       @method = m
1465       @request_has_body = reqbody
1466       @response_has_body = resbody
1467       raise ArgumentError, "HTTP request path is empty" if path.empty?
1468       @path = path
1469       initialize_http_header initheader
1470       self['Accept'] ||= '*/*'
1471       @body = nil
1472       @body_stream = nil
1473     end
1475     attr_reader :method
1476     attr_reader :path
1478     def inspect
1479       "\#<#{self.class} #{@method}>"
1480     end
1482     def request_body_permitted?
1483       @request_has_body
1484     end
1486     def response_body_permitted?
1487       @response_has_body
1488     end
1490     def body_exist?
1491       warn "Net::HTTPRequest#body_exist? is obsolete; use response_body_permitted?" if $VERBOSE
1492       response_body_permitted?
1493     end
1495     attr_reader :body
1497     def body=(str)
1498       @body = str
1499       @body_stream = nil
1500       str
1501     end
1503     attr_reader :body_stream
1505     def body_stream=(input)
1506       @body = nil
1507       @body_stream = input
1508       input
1509     end
1511     def set_body_internal(str)   #:nodoc: internal use only
1512       raise ArgumentError, "both of body argument and HTTPRequest#body set" if str and (@body or @body_stream)
1513       self.body = str if str
1514     end
1516     #
1517     # write
1518     #
1520     def exec(sock, ver, path)   #:nodoc: internal use only
1521       if @body
1522         send_request_with_body sock, ver, path, @body
1523       elsif @body_stream
1524         send_request_with_body_stream sock, ver, path, @body_stream
1525       else
1526         write_header sock, ver, path
1527       end
1528     end
1530     private
1532     def send_request_with_body(sock, ver, path, body)
1533       self.content_length = body.length
1534       delete 'Transfer-Encoding'
1535       supply_default_content_type
1536       write_header sock, ver, path
1537       sock.write body
1538     end
1540     def send_request_with_body_stream(sock, ver, path, f)
1541       unless content_length() or chunked?
1542         raise ArgumentError,
1543             "Content-Length not given and Transfer-Encoding is not `chunked'"
1544       end
1545       supply_default_content_type
1546       write_header sock, ver, path
1547       if chunked?
1548         while s = f.read(1024)
1549           sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
1550         end
1551         sock.write "0\r\n\r\n"
1552       else
1553         while s = f.read(1024)
1554           sock.write s
1555         end
1556       end
1557     end
1559     def supply_default_content_type
1560       return if content_type()
1561       warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE
1562       set_content_type 'application/x-www-form-urlencoded'
1563     end
1565     def write_header(sock, ver, path)
1566       buf = "#{@method} #{path} HTTP/#{ver}\r\n"
1567       each_capitalized do |k,v|
1568         buf << "#{k}: #{v}\r\n"
1569       end
1570       buf << "\r\n"
1571       sock.write buf
1572     end
1573   
1574   end
1577   # 
1578   # HTTP request class. This class wraps request header and entity path.
1579   # You *must* use its subclass, Net::HTTP::Get, Post, Head.
1580   # 
1581   class HTTPRequest < HTTPGenericRequest
1583     # Creates HTTP request object.
1584     def initialize(path, initheader = nil)
1585       super self.class::METHOD,
1586             self.class::REQUEST_HAS_BODY,
1587             self.class::RESPONSE_HAS_BODY,
1588             path, initheader
1589     end
1590   end
1593   class HTTP   # reopen
1594     #
1595     # HTTP 1.1 methods --- RFC2616
1596     #
1598     class Get < HTTPRequest
1599       METHOD = 'GET'
1600       REQUEST_HAS_BODY  = false
1601       RESPONSE_HAS_BODY = true
1602     end
1604     class Head < HTTPRequest
1605       METHOD = 'HEAD'
1606       REQUEST_HAS_BODY = false
1607       RESPONSE_HAS_BODY = false
1608     end
1610     class Post < HTTPRequest
1611       METHOD = 'POST'
1612       REQUEST_HAS_BODY = true
1613       RESPONSE_HAS_BODY = true
1614     end
1616     class Put < HTTPRequest
1617       METHOD = 'PUT'
1618       REQUEST_HAS_BODY = true
1619       RESPONSE_HAS_BODY = true
1620     end
1622     class Delete < HTTPRequest
1623       METHOD = 'DELETE'
1624       REQUEST_HAS_BODY = false
1625       RESPONSE_HAS_BODY = true
1626     end
1628     class Options < HTTPRequest
1629       METHOD = 'OPTIONS'
1630       REQUEST_HAS_BODY = false
1631       RESPONSE_HAS_BODY = false
1632     end
1634     class Trace < HTTPRequest
1635       METHOD = 'TRACE'
1636       REQUEST_HAS_BODY = false
1637       RESPONSE_HAS_BODY = true
1638     end
1640     #
1641     # WebDAV methods --- RFC2518
1642     #
1644     class Propfind < HTTPRequest
1645       METHOD = 'PROPFIND'
1646       REQUEST_HAS_BODY = true
1647       RESPONSE_HAS_BODY = true
1648     end
1650     class Proppatch < HTTPRequest
1651       METHOD = 'PROPPATCH'
1652       REQUEST_HAS_BODY = true
1653       RESPONSE_HAS_BODY = true
1654     end
1656     class Mkcol < HTTPRequest
1657       METHOD = 'MKCOL'
1658       REQUEST_HAS_BODY = true
1659       RESPONSE_HAS_BODY = true
1660     end
1662     class Copy < HTTPRequest
1663       METHOD = 'COPY'
1664       REQUEST_HAS_BODY = false
1665       RESPONSE_HAS_BODY = true
1666     end
1668     class Move < HTTPRequest
1669       METHOD = 'MOVE'
1670       REQUEST_HAS_BODY = false
1671       RESPONSE_HAS_BODY = true
1672     end
1674     class Lock < HTTPRequest
1675       METHOD = 'LOCK'
1676       REQUEST_HAS_BODY = true
1677       RESPONSE_HAS_BODY = true
1678     end
1680     class Unlock < HTTPRequest
1681       METHOD = 'UNLOCK'
1682       REQUEST_HAS_BODY = true
1683       RESPONSE_HAS_BODY = true
1684     end
1685   end
1688   ###
1689   ### Response
1690   ###
1692   # HTTP exception class.
1693   # You must use its subclasses.
1694   module HTTPExceptions
1695     def initialize(msg, res)   #:nodoc:
1696       super msg
1697       @response = res
1698     end
1699     attr_reader :response
1700     alias data response    #:nodoc: obsolete
1701   end
1702   class HTTPError < ProtocolError
1703     include HTTPExceptions
1704   end
1705   class HTTPRetriableError < ProtoRetriableError
1706     include HTTPExceptions
1707   end
1708   class HTTPServerException < ProtoServerError
1709     # We cannot use the name "HTTPServerError", it is the name of the response.
1710     include HTTPExceptions
1711   end
1712   class HTTPFatalError < ProtoFatalError
1713     include HTTPExceptions
1714   end
1717   # HTTP response class. This class wraps response header and entity.
1718   # Mixes in the HTTPHeader module, which provides access to response
1719   # header values both via hash-like methods and individual readers.
1720   # Note that each possible HTTP response code defines its own 
1721   # HTTPResponse subclass.  These are listed below.
1722   # All classes are
1723   # defined under the Net module. Indentation indicates inheritance.
1724   # 
1725   #   xxx        HTTPResponse
1726   # 
1727   #     1xx        HTTPInformation
1728   #       100        HTTPContinue    
1729   #       101        HTTPSwitchProtocol
1730   # 
1731   #     2xx        HTTPSuccess
1732   #       200        HTTPOK
1733   #       201        HTTPCreated
1734   #       202        HTTPAccepted
1735   #       203        HTTPNonAuthoritativeInformation
1736   #       204        HTTPNoContent
1737   #       205        HTTPResetContent
1738   #       206        HTTPPartialContent
1739   # 
1740   #     3xx        HTTPRedirection
1741   #       300        HTTPMultipleChoice
1742   #       301        HTTPMovedPermanently
1743   #       302        HTTPFound
1744   #       303        HTTPSeeOther
1745   #       304        HTTPNotModified
1746   #       305        HTTPUseProxy
1747   #       307        HTTPTemporaryRedirect
1748   # 
1749   #     4xx        HTTPClientError
1750   #       400        HTTPBadRequest
1751   #       401        HTTPUnauthorized
1752   #       402        HTTPPaymentRequired
1753   #       403        HTTPForbidden
1754   #       404        HTTPNotFound
1755   #       405        HTTPMethodNotAllowed
1756   #       406        HTTPNotAcceptable
1757   #       407        HTTPProxyAuthenticationRequired
1758   #       408        HTTPRequestTimeOut
1759   #       409        HTTPConflict
1760   #       410        HTTPGone
1761   #       411        HTTPLengthRequired
1762   #       412        HTTPPreconditionFailed
1763   #       413        HTTPRequestEntityTooLarge
1764   #       414        HTTPRequestURITooLong
1765   #       415        HTTPUnsupportedMediaType
1766   #       416        HTTPRequestedRangeNotSatisfiable
1767   #       417        HTTPExpectationFailed
1768   # 
1769   #     5xx        HTTPServerError
1770   #       500        HTTPInternalServerError
1771   #       501        HTTPNotImplemented
1772   #       502        HTTPBadGateway
1773   #       503        HTTPServiceUnavailable
1774   #       504        HTTPGatewayTimeOut
1775   #       505        HTTPVersionNotSupported
1776   # 
1777   #     xxx        HTTPUnknownResponse
1778   #
1779   class HTTPResponse
1780     # true if the response has body.
1781     def HTTPResponse.body_permitted?
1782       self::HAS_BODY
1783     end
1785     def HTTPResponse.exception_type   # :nodoc: internal use only
1786       self::EXCEPTION_TYPE
1787     end
1788   end   # reopened after
1790   # :stopdoc:
1792   class HTTPUnknownResponse < HTTPResponse
1793     HAS_BODY = true
1794     EXCEPTION_TYPE = HTTPError
1795   end
1796   class HTTPInformation < HTTPResponse           # 1xx
1797     HAS_BODY = false
1798     EXCEPTION_TYPE = HTTPError
1799   end
1800   class HTTPSuccess < HTTPResponse               # 2xx
1801     HAS_BODY = true
1802     EXCEPTION_TYPE = HTTPError
1803   end
1804   class HTTPRedirection < HTTPResponse           # 3xx
1805     HAS_BODY = true
1806     EXCEPTION_TYPE = HTTPRetriableError
1807   end
1808   class HTTPClientError < HTTPResponse           # 4xx
1809     HAS_BODY = true
1810     EXCEPTION_TYPE = HTTPServerException   # for backward compatibility
1811   end
1812   class HTTPServerError < HTTPResponse           # 5xx
1813     HAS_BODY = true
1814     EXCEPTION_TYPE = HTTPFatalError    # for backward compatibility
1815   end
1817   class HTTPContinue < HTTPInformation           # 100
1818     HAS_BODY = false
1819   end
1820   class HTTPSwitchProtocol < HTTPInformation     # 101
1821     HAS_BODY = false
1822   end
1824   class HTTPOK < HTTPSuccess                            # 200
1825     HAS_BODY = true
1826   end
1827   class HTTPCreated < HTTPSuccess                       # 201
1828     HAS_BODY = true
1829   end
1830   class HTTPAccepted < HTTPSuccess                      # 202
1831     HAS_BODY = true
1832   end
1833   class HTTPNonAuthoritativeInformation < HTTPSuccess   # 203
1834     HAS_BODY = true
1835   end
1836   class HTTPNoContent < HTTPSuccess                     # 204
1837     HAS_BODY = false
1838   end
1839   class HTTPResetContent < HTTPSuccess                  # 205
1840     HAS_BODY = false
1841   end
1842   class HTTPPartialContent < HTTPSuccess                # 206
1843     HAS_BODY = true
1844   end
1846   class HTTPMultipleChoice < HTTPRedirection     # 300
1847     HAS_BODY = true
1848   end
1849   class HTTPMovedPermanently < HTTPRedirection   # 301
1850     HAS_BODY = true
1851   end
1852   class HTTPFound < HTTPRedirection              # 302
1853     HAS_BODY = true
1854   end
1855   HTTPMovedTemporarily = HTTPFound
1856   class HTTPSeeOther < HTTPRedirection           # 303
1857     HAS_BODY = true
1858   end
1859   class HTTPNotModified < HTTPRedirection        # 304
1860     HAS_BODY = false
1861   end
1862   class HTTPUseProxy < HTTPRedirection           # 305
1863     HAS_BODY = false
1864   end
1865   # 306 unused
1866   class HTTPTemporaryRedirect < HTTPRedirection  # 307
1867     HAS_BODY = true
1868   end
1870   class HTTPBadRequest < HTTPClientError                    # 400
1871     HAS_BODY = true
1872   end
1873   class HTTPUnauthorized < HTTPClientError                  # 401
1874     HAS_BODY = true
1875   end
1876   class HTTPPaymentRequired < HTTPClientError               # 402
1877     HAS_BODY = true
1878   end
1879   class HTTPForbidden < HTTPClientError                     # 403
1880     HAS_BODY = true
1881   end
1882   class HTTPNotFound < HTTPClientError                      # 404
1883     HAS_BODY = true
1884   end
1885   class HTTPMethodNotAllowed < HTTPClientError              # 405
1886     HAS_BODY = true
1887   end
1888   class HTTPNotAcceptable < HTTPClientError                 # 406
1889     HAS_BODY = true
1890   end
1891   class HTTPProxyAuthenticationRequired < HTTPClientError   # 407
1892     HAS_BODY = true
1893   end
1894   class HTTPRequestTimeOut < HTTPClientError                # 408
1895     HAS_BODY = true
1896   end
1897   class HTTPConflict < HTTPClientError                      # 409
1898     HAS_BODY = true
1899   end
1900   class HTTPGone < HTTPClientError                          # 410
1901     HAS_BODY = true
1902   end
1903   class HTTPLengthRequired < HTTPClientError                # 411
1904     HAS_BODY = true
1905   end
1906   class HTTPPreconditionFailed < HTTPClientError            # 412
1907     HAS_BODY = true
1908   end
1909   class HTTPRequestEntityTooLarge < HTTPClientError         # 413
1910     HAS_BODY = true
1911   end
1912   class HTTPRequestURITooLong < HTTPClientError             # 414
1913     HAS_BODY = true
1914   end
1915   HTTPRequestURITooLarge = HTTPRequestURITooLong
1916   class HTTPUnsupportedMediaType < HTTPClientError          # 415
1917     HAS_BODY = true
1918   end
1919   class HTTPRequestedRangeNotSatisfiable < HTTPClientError  # 416
1920     HAS_BODY = true
1921   end
1922   class HTTPExpectationFailed < HTTPClientError             # 417
1923     HAS_BODY = true
1924   end
1926   class HTTPInternalServerError < HTTPServerError   # 500
1927     HAS_BODY = true
1928   end
1929   class HTTPNotImplemented < HTTPServerError        # 501
1930     HAS_BODY = true
1931   end
1932   class HTTPBadGateway < HTTPServerError            # 502
1933     HAS_BODY = true
1934   end
1935   class HTTPServiceUnavailable < HTTPServerError    # 503
1936     HAS_BODY = true
1937   end
1938   class HTTPGatewayTimeOut < HTTPServerError        # 504
1939     HAS_BODY = true
1940   end
1941   class HTTPVersionNotSupported < HTTPServerError   # 505
1942     HAS_BODY = true
1943   end
1945   # :startdoc:
1948   class HTTPResponse   # reopen
1950     CODE_CLASS_TO_OBJ = {
1951       '1' => HTTPInformation,
1952       '2' => HTTPSuccess,
1953       '3' => HTTPRedirection,
1954       '4' => HTTPClientError,
1955       '5' => HTTPServerError
1956     }
1957     CODE_TO_OBJ = {
1958       '100' => HTTPContinue,
1959       '101' => HTTPSwitchProtocol,
1961       '200' => HTTPOK,
1962       '201' => HTTPCreated,
1963       '202' => HTTPAccepted,
1964       '203' => HTTPNonAuthoritativeInformation,
1965       '204' => HTTPNoContent,
1966       '205' => HTTPResetContent,
1967       '206' => HTTPPartialContent,
1969       '300' => HTTPMultipleChoice,
1970       '301' => HTTPMovedPermanently,
1971       '302' => HTTPFound,
1972       '303' => HTTPSeeOther,
1973       '304' => HTTPNotModified,
1974       '305' => HTTPUseProxy,
1975       '307' => HTTPTemporaryRedirect,
1977       '400' => HTTPBadRequest,
1978       '401' => HTTPUnauthorized,
1979       '402' => HTTPPaymentRequired,
1980       '403' => HTTPForbidden,
1981       '404' => HTTPNotFound,
1982       '405' => HTTPMethodNotAllowed,
1983       '406' => HTTPNotAcceptable,
1984       '407' => HTTPProxyAuthenticationRequired,
1985       '408' => HTTPRequestTimeOut,
1986       '409' => HTTPConflict,
1987       '410' => HTTPGone,
1988       '411' => HTTPLengthRequired,
1989       '412' => HTTPPreconditionFailed,
1990       '413' => HTTPRequestEntityTooLarge,
1991       '414' => HTTPRequestURITooLong,
1992       '415' => HTTPUnsupportedMediaType,
1993       '416' => HTTPRequestedRangeNotSatisfiable,
1994       '417' => HTTPExpectationFailed,
1996       '500' => HTTPInternalServerError,
1997       '501' => HTTPNotImplemented,
1998       '502' => HTTPBadGateway,
1999       '503' => HTTPServiceUnavailable,
2000       '504' => HTTPGatewayTimeOut,
2001       '505' => HTTPVersionNotSupported
2002     }
2004     class << HTTPResponse
2005       def read_new(sock)   #:nodoc: internal use only
2006         httpv, code, msg = read_status_line(sock)
2007         res = response_class(code).new(httpv, code, msg)
2008         each_response_header(sock) do |k,v|
2009           res.add_field k, v
2010         end
2011         res
2012       end
2014       private
2016       def read_status_line(sock)
2017         str = sock.readline
2018         m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str) or
2019           raise HTTPBadResponse, "wrong status line: #{str.dump}"
2020         m.captures
2021       end
2023       def response_class(code)
2024         CODE_TO_OBJ[code] or
2025         CODE_CLASS_TO_OBJ[code[0,1]] or
2026         HTTPUnknownResponse
2027       end
2029       def each_response_header(sock)
2030         while true
2031           line = sock.readuntil("\n", true).sub(/\s+\z/, '')
2032           break if line.empty?
2033           m = /\A([^:]+):\s*/.match(line) or
2034               raise HTTPBadResponse, 'wrong header line format'
2035           yield m[1], m.post_match
2036         end
2037       end
2038     end
2040     # next is to fix bug in RDoc, where the private inside class << self
2041     # spills out.
2042     public 
2044     include HTTPHeader
2046     def initialize(httpv, code, msg)   #:nodoc: internal use only
2047       @http_version = httpv
2048       @code         = code
2049       @message      = msg
2050       initialize_http_header nil
2051       @body = nil
2052       @read = false
2053     end
2055     # The HTTP version supported by the server.
2056     attr_reader :http_version
2058     # HTTP result code string. For example, '302'.  You can also
2059     # determine the response type by which response subclass the
2060     # response object is an instance of.
2061     attr_reader :code
2063     # HTTP result message. For example, 'Not Found'.
2064     attr_reader :message
2065     alias msg message   # :nodoc: obsolete
2067     def inspect
2068       "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
2069     end
2071     # For backward compatibility.
2072     # To allow Net::HTTP 1.1 style assignment
2073     # e.g.
2074     #    response, body = Net::HTTP.get(....)
2075     # 
2076     def to_ary
2077       warn "net/http.rb: warning: Net::HTTP v1.1 style assignment found at #{caller(1)[0]}; use `response = http.get(...)' instead." if $VERBOSE
2078       res = self.dup
2079       class << res
2080         undef to_ary
2081       end
2082       [res, res.body]
2083     end
2085     #
2086     # response <-> exception relationship
2087     #
2089     def code_type   #:nodoc:
2090       self.class
2091     end
2093     def error!   #:nodoc:
2094       raise error_type().new(@code + ' ' + @message.dump, self)
2095     end
2097     def error_type   #:nodoc:
2098       self.class::EXCEPTION_TYPE
2099     end
2101     # Raises HTTP error if the response is not 2xx.
2102     def value
2103       error! unless self.kind_of?(HTTPSuccess)
2104     end
2106     #
2107     # header (for backward compatibility only; DO NOT USE)
2108     #
2110     def response   #:nodoc:
2111       warn "#{caller(1)[0]}: warning: HTTPResponse#response is obsolete" if $VERBOSE
2112       self
2113     end
2115     def header   #:nodoc:
2116       warn "#{caller(1)[0]}: warning: HTTPResponse#header is obsolete" if $VERBOSE
2117       self
2118     end
2120     def read_header   #:nodoc:
2121       warn "#{caller(1)[0]}: warning: HTTPResponse#read_header is obsolete" if $VERBOSE
2122       self
2123     end
2125     #
2126     # body
2127     #
2129     def reading_body(sock, reqmethodallowbody)  #:nodoc: internal use only
2130       @socket = sock
2131       @body_exist = reqmethodallowbody && self.class.body_permitted?
2132       begin
2133         yield
2134         self.body   # ensure to read body
2135       ensure
2136         @socket = nil
2137       end
2138     end
2140     # Gets entity body.  If the block given, yields it to +block+.
2141     # The body is provided in fragments, as it is read in from the socket.
2142     #
2143     # Calling this method a second or subsequent time will return the
2144     # already read string.
2145     #
2146     #   http.request_get('/index.html') {|res|
2147     #     puts res.read_body
2148     #   }
2149     #
2150     #   http.request_get('/index.html') {|res|
2151     #     p res.read_body.object_id   # 538149362
2152     #     p res.read_body.object_id   # 538149362
2153     #   }
2154     #
2155     #   # using iterator
2156     #   http.request_get('/index.html') {|res|
2157     #     res.read_body do |segment|
2158     #       print segment
2159     #     end
2160     #   }
2161     #
2162     def read_body(dest = nil, &block)
2163       if @read
2164         raise IOError, "#{self.class}\#read_body called twice" if dest or block
2165         return @body
2166       end
2167       to = procdest(dest, block)
2168       stream_check
2169       if @body_exist
2170         read_body_0 to
2171         @body = to
2172       else
2173         @body = nil
2174       end
2175       @read = true
2177       @body
2178     end
2180     # Returns the entity body.
2181     #
2182     # Calling this method a second or subsequent time will return the
2183     # already read string.
2184     #
2185     #   http.request_get('/index.html') {|res|
2186     #     puts res.body
2187     #   }
2188     #
2189     #   http.request_get('/index.html') {|res|
2190     #     p res.body.object_id   # 538149362
2191     #     p res.body.object_id   # 538149362
2192     #   }
2193     #
2194     def body
2195       read_body()
2196     end
2198     alias entity body   #:nodoc: obsolete
2200     private
2202     def read_body_0(dest)
2203       if chunked?
2204         read_chunked dest
2205         return
2206       end
2207       clen = content_length()
2208       if clen
2209         @socket.read clen, dest, true   # ignore EOF
2210         return
2211       end
2212       clen = range_length()
2213       if clen
2214         @socket.read clen, dest
2215         return
2216       end
2217       @socket.read_all dest
2218     end
2220     def read_chunked(dest)
2221       len = nil
2222       total = 0
2223       while true
2224         line = @socket.readline
2225         hexlen = line.slice(/[0-9a-fA-F]+/) or
2226             raise HTTPBadResponse, "wrong chunk size line: #{line}"
2227         len = hexlen.hex
2228         break if len == 0
2229         @socket.read len, dest; total += len
2230         @socket.read 2   # \r\n
2231       end
2232       until @socket.readline.empty?
2233         # none
2234       end
2235     end
2237     def stream_check
2238       raise IOError, 'attempt to read body out of block' if @socket.closed?
2239     end
2241     def procdest(dest, block)
2242       raise ArgumentError, 'both arg and block given for HTTP method' \
2243           if dest and block
2244       if block
2245         ReadAdapter.new(block)
2246       else
2247         dest || ''
2248       end
2249     end
2251   end
2254   # :enddoc:
2256   #--
2257   # for backward compatibility
2258   class HTTP
2259     ProxyMod = ProxyDelta
2260   end
2261   module NetPrivate
2262     HTTPRequest = ::Net::HTTPRequest
2263   end
2265   HTTPInformationCode = HTTPInformation
2266   HTTPSuccessCode     = HTTPSuccess
2267   HTTPRedirectionCode = HTTPRedirection
2268   HTTPRetriableCode   = HTTPRedirection
2269   HTTPClientErrorCode = HTTPClientError
2270   HTTPFatalErrorCode  = HTTPClientError
2271   HTTPServerErrorCode = HTTPServerError
2272   HTTPResponceReceiver = HTTPResponse
2274 end   # module Net