diff options
author | aamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-06-26 23:49:21 +0000 |
---|---|---|
committer | aamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-06-26 23:49:21 +0000 |
commit | c664027a342785089cc09169ff167350e840baa9 (patch) | |
tree | 2b74c20ddbfd9371414294e4c34ea3ce1e5afe95 /lib/net/http.rb | |
parent | 10e80b2402f7c0fd79df86767a11ba4e4b1bfa95 (diff) | |
download | ruby-c664027a342785089cc09169ff167350e840baa9.tar.gz |
aamine
* lib/net/pop.rb: new methods POP3.auth_only, POP3#auth_only
* lib/net/http.rb: HTTP.Proxy returns self if ADDRESS is nil.
* lib/net/protocol.rb: new method ProtocolError#response
* lib/net/protocol.rb,smtp.rb,pop.rb,http.rb: add document.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1546 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/net/http.rb')
-rw-r--r-- | lib/net/http.rb | 488 |
1 files changed, 328 insertions, 160 deletions
diff --git a/lib/net/http.rb b/lib/net/http.rb index bbe98274f4..6a8fc5f862 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1,125 +1,304 @@ =begin -= net/http.rb version 1.2.0 += net/http.rb version 1.2.1 - Copyright (C) 1999-2001 Yukihiro Matsumoto +Copyright (c) 1999-2001 Yukihiro Matsumoto - written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp> - This file is derived from "http-access.rb". +written & maintained by Minero Aoki <aamine@loveruby.net> +This file is derived from "http-access.rb". - This program is free software. You can re-distribute and/or - modify this program under the same terms as Ruby itself, - GNU General Public License or Ruby License. +This program is free software. You can re-distribute and/or +modify this program under the same terms as Ruby itself, +Ruby Distribute License or GNU General Public License. - Japanese version of this document is in "net" full package. - You can get it from RAA (Ruby Application Archive). RAA is: - http://www.ruby-lang.org/en/raa.html +NOTE: You can get Japanese version of this document from +Ruby Documentation Project (RDP): +((<URL:http://www.ruby-lang.org/~rubikitch/RDP.cgi>)) +== What is this module? + +This module provide your program the functions to access WWW +documents via HTTP, Hyper Text Transfer Protocol version 1.1. +For details of HTTP, refer [RFC2616] +((<URL:http://www.ietf.org/rfc/rfc2616.txt>)). + +== Examples + +=== Getting Document From Server + +Be care to ',' (comma) putted after "response". +This is required for feature compatibility. + + require 'net/http' + Net::HTTP.start( 'some.www.server', 80 ) {|http| + response , = http.get('/index.html') + puts response.body + } + +(shorter version) + + require 'net/http' + Net::HTTP.get_print 'some.www.server', '/index.html' + +=== Posting Form Data + + require 'net/http' + Net::HTTP.start( 'some.www.server', 80 ) {|http| + response , = http.post( '/cgi-bin/any.rhtml', + 'querytype=subject&target=ruby' ) + } + +=== Accessing via Proxy + +Net::HTTP.Proxy() creates http proxy class. It has same +methods of Net::HTTP but its instances always connect to +proxy, instead of given host. + + require 'net/http' + + $proxy_addr = 'your.proxy.addr' + $proxy_port = 8080 + : + Net::HTTP::Proxy($proxy_addr, $proxy_port).start( 'some.www.server' ) {|http| + # always connect to your.proxy.addr:8080 + : + } + +Since Net::HTTP.Proxy() returns Net::HTTP itself when $proxy_addr is nil, +there's no need to change code if there's proxy or not. + +=== Redirect + + require 'net/http' + Net::HTTP.version_1_1 + + host = 'www.ruby-lang.org' + begin + Net::HTTP.start( host, 80 ) {|http| + response , = http.get('/') + } + rescue Net::ProtoRetriableError => err + if m = %r<http:([^/]+)>.match( err.response['location'] ) then + host = m[1].strip + retry + end + end + +NOTE: This code is using ad-hoc way to extract host name, but in future +URI class will be included in ruby standard library. + +=== Basic Authentication + + require 'net/http' + + Net::HTTP.start( 'auth.some.domain' ) {|http| + response , = http.get( '/need-auth.cgi', + 'Authentication' => ["#{account}:#{password}"].pack('m').strip ) + print response.body + } + +In version 1.2 (Ruby 1.7 or later), you can write like this: + + require 'net/http' + + req = Net::HTTP::Get.new('/need-auth.cgi') + req.basic_auth 'account', 'password' + Net::HTTP.start( 'auth.some.domain' ) {|http| + response = http.request( req ) + print response.body + } + +== Switching Net::HTTP versions + +You can use old Net::HTTP (in Ruby 1.6) features by calling +HTTP.version_1_1. And calling Net::HTTP.version_1_2 allows +you to use 1.2 features again. + + # example + Net::HTTP.start {|http1| ...(http1 has 1.2 features)... } + + Net::HTTP.version_1_1 + Net::HTTP.start {|http2| ...(http2 has 1.1 features)... } + + Net::HTTP.version_1_2 + Net::HTTP.start {|http3| ...(http3 has 1.2 features)... } + +Yes, this is not thread-safe. == class Net::HTTP === Class Methods : new( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil ) - creates a new Net::HTTP object. - If proxy_addr is given, this method is equals to - Net::HTTP::Proxy(proxy_addr,proxy_port). + creates a new Net::HTTP object. + If proxy_addr is given, this method is equals to + Net::HTTP::Proxy(proxy_addr,proxy_port). : start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil ) : start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil ) {|http| .... } - is equals to + is equals to - Net::HTTP.new( address, port, proxy_addr, proxy_port ).start(&block) + Net::HTTP.new(address, port, proxy_addr, proxy_port).start(&block) : get( address, path, port = 80 ) - gets entity body from path and returns it. - return value is a String. + gets entity body from path and returns it. + return value is a String. : get_print( address, path, port = 80 ) - gets entity body from path and print it. - return value is an entity body (a String). - -: Proxy( address, port ) - creates a HTTP proxy class. - Arguments are address/port of proxy host. - You can replace HTTP class by this proxy class. - - # example - proxy_http = HTTP::Proxy( 'proxy.foo.org', 8080 ) - : - proxy_http.start( 'www.ruby-lang.org' ) do |http| - # connecting proxy.foo.org:8080 - : - end + gets entity body from path and print it. + return value is an entity body (a String). + +: Proxy( address, port = 80 ) + creates a HTTP proxy class. + Arguments are address/port of proxy host. + You can replace HTTP class by this proxy class. + + If ADDRESS is nil, this method returns self (Net::HTTP class). + + # example + proxy_class = Net::HTTP::Proxy( 'proxy.foo.org', 8080 ) + : + proxy_class.start( 'www.ruby-lang.org' ) do |http| + # connecting proxy.foo.org:8080 + : + end : proxy_class? - If self is HTTP, false. - If self is a class which was created by HTTP::Proxy(), true. + If self is HTTP, false. + If self is a class which was created by HTTP::Proxy(), true. : port - HTTP default port (80). - + HTTP default port (80). === Instance Methods : start : start {|http| .... } - creates a new Net::HTTP object and starts HTTP session. + creates a new Net::HTTP object and starts HTTP session. + + When this method is called with block, gives a HTTP object to block + and close the HTTP session after block call finished. + +: active? + true if HTTP session is started. + +: address + the address to connect + +: port + the port number to connect - When this method is called with block, gives HTTP object to block - and close HTTP session after block call finished. +: open_timeout +: open_timeout=(n) + seconds to wait until connection is opened. + If HTTP object cannot open a conection in this seconds, + it raises TimeoutError exception. + +: read_timeout +: read_timeout=(n) + seconds to wait until reading one block (by one read(1) call). + If HTTP object cannot open a conection in this seconds, + it raises TimeoutError exception. + +: finish + finishes HTTP session. + If HTTP session had not started, do nothing and return false. : proxy? - true if self is a HTTP proxy class + true if self is a HTTP proxy class : proxy_address - address of proxy host. If self is not a proxy, nil. + address of proxy host. If self is not a proxy, nil. : proxy_port - port number of proxy host. If self is not a proxy, nil. + port number of proxy host. If self is not a proxy, nil. : get( path, header = nil, dest = '' ) : get( path, header = nil ) {|str| .... } - gets data from "path" on connecting host. - "header" must be a Hash like { 'Accept' => '*/*', ... }. - Response body is written into "dest" by using "<<" method. - This method returns Net::HTTPResponse object. + gets data from "path" on connecting host. + "header" must be a Hash like { 'Accept' => '*/*', ... }. + Response body is written into "dest" by using "<<" method. + This method returns Net::HTTPResponse object. - # example - response = http.get( '/index.html' ) + If called with block, give a part String of entity body. - If called with block, give a part String of entity body. + In version 1.1, this method might raises exception for also + 3xx (redirect). On the case you can get response object by + err.response. -: head( path, header = nil ) - gets only header from "path" on connecting host. - "header" is a Hash like { 'Accept' => '*/*', ... }. - This method returns a Net::HTTPResponse object. - You can http header from this object like: + In version 1.2, this method never raises exception. - response['content-length'] #-> '2554' - response['content-type'] #-> 'text/html' - response['Content-Type'] #-> 'text/html' - response['CoNtEnT-tYpe'] #-> 'text/html' + # version 1.1 (Ruby 1.6) + response, body = http.get( '/index.html' ) -: post( path, data, header = nil, dest = '' ) -: post( path, data, header = nil ) {|str| .... } - posts "data" (must be String) to "path". - If the body exists, also gets entity body. - Response body is written into "dest" by using "<<" method. - "header" must be a Hash like { 'Accept' => '*/*', ... }. - This method returns Net::HTTPResponse object. + # version 1.2 (Ruby 1.7 or later) + response = http.get( '/index.html' ) - If called with block, gives a part of entity body string. + # compatible in both version + response , = http.get( '/index.html' ) + response.body + + # using block + File.open( 'save.txt', 'w' ) {|f| + http.get( '/~foo/', nil ) do |str| + f.write str + end + } + # some effect + File.open( 'save.txt', 'w' ) {|f| + http.get '/~foo/', nil, f + } +: head( path, header = nil ) + gets only header from "path" on connecting host. + "header" is a Hash like { 'Accept' => '*/*', ... }. + This method returns a Net::HTTPResponse object. + You can http header from this object like: + + response = nil + Net::HTTP.start( 'some.www.server', 80 ) {|http| + response = http.head( '/index.html' ) + } + response['content-length'] #-> '2554' + response['content-type'] #-> 'text/html' + response['Content-Type'] #-> 'text/html' + response['CoNtEnT-tYpe'] #-> 'text/html' -: request( request, [src] ) -: request( request, [src] ) {|response| .... } - sends REQUEST to (remote) http server. This method also writes - string from SRC before it if REQUEST is a post/put request. - (giving SRC for get/head request causes ArgumentError.) +: post( path, data, header = nil, dest = '' ) +: post( path, data, header = nil ) {|str| .... } + posts "data" (must be String) to "path". + If the body exists, also gets entity body. + Response body is written into "dest" by using "<<" method. + "header" must be a Hash like { 'Accept' => '*/*', ... }. + This method returns Net::HTTPResponse object. + + If called with block, gives a part of entity body string. + + # version 1.1 + response, body = http.post( '/index.html', 'querytype=subject&target=ruby' ) + # version 1.2 + response = http.post( '/index.html', 'querytype=subject&target=ruby' ) + # compatible for both version + response , = http.post( '/index.html', 'querytype=subject&target=ruby' ) + + # using block + File.open( 'save.html', 'w' ) {|f| + http.post( '/index.html', 'querytype=subject&target=ruby' ) do |str| + f.write str + end + } + # same effect + File.open( 'save.html', 'w' ) {|f| + http.post '/index.html', 'querytype=subject&target=ruby', nil, f + } - If called with block, gives a HTTP response object to the block. +: request( request, [data] ) +: request( request, [src] ) {|response| .... } + sends REQUEST to (remote) http server. This method also writes + string from DATA string if REQUEST is a post/put request. + (giving DATA for get/head request causes ArgumentError.) + If called with block, gives a HTTPResponse object to the block. == class Net::HTTP::Get, Head, Post @@ -131,7 +310,7 @@ entity path. All arguments named "key" is case-insensitive. : new creats HTTP request object. -=== Methods +=== Instance Methods : self[ key ] returns the header field corresponding to the case-insensitive key. @@ -140,13 +319,32 @@ entity path. All arguments named "key" is case-insensitive. : self[ key ] = val sets the header field corresponding to the case-insensitive key. +: each {|name, val| .... } + iterates for each field name and value pair. + +: basic_auth( account, password ) + set Authorization: header for basic auth. + +: range + returns a Range object which represents Range: header field. + +: range = r +: set_range( i, len ) + set Range: header from Range (arg r) or beginning index and + length from it (arg i&len). + +: content_length + returns a Integer object which represents Content-Length: header field. + +: content_range + returns a Range object which represents Content-Range: header field. == class Net::HTTPResponse HTTP response class. This class wraps response header and entity. All arguments named KEY is case-insensitive. -=== Methods +=== Instance Methods : self[ key ] returns the header field corresponding to the case-insensitive key. @@ -166,7 +364,7 @@ All arguments named KEY is case-insensitive. iterates for each field name and value pair. : canonical_each {|name,value| .... } - iterates for each canonical field name and value pair. + iterates for each "canonical" field name and value pair. : code HTTP result code string. For example, '302'. @@ -175,34 +373,18 @@ All arguments named KEY is case-insensitive. HTTP result message. For example, 'Not Found'. : read_body( dest = '' ) - gets response body and write it into DEST using "<<" method. + gets entity body and write it into DEST using "<<" method. If this method is called twice or more, nothing will be done and returns first DEST. : read_body {|str| .... } - gets response body little by little and pass it to block. + gets entity body little by little and pass it to block. : body - response body. If #read_body has been called, this method - returns arg of #read_body, DEST. Else gets body as String - and returns it. + response body. If #read_body has been called, this method returns + arg of #read_body DEST. Else gets body as String and returns it. -== Switching Net::HTTP versions - -You can use Net::HTTP 1.1 features by calling HTTP.version_1_1 . -And calling Net::HTTP.version_1_2 allows you to use 1.2 features -again. - - # example - HTTP.start {|http1| ...(http1 has 1.2 features)... } - - HTTP.version_1_1 - HTTP.start {|http2| ...(http2 has 1.1 features)... } - - HTTP.version_1_2 - HTTP.start {|http3| ...(http3 has 1.2 features)... } - =end require 'net/protocol' @@ -224,18 +406,13 @@ module Net protocol_param :port, '80' - def initialize( addr = nil, port = nil ) super - @proxy_address = nil - @proxy_port = nil - @curr_http_version = HTTPVersion @seems_1_0_server = false end - private def conn_command( sock ) @@ -255,7 +432,11 @@ module Net class << self def Proxy( p_addr, p_port = nil ) - ProxyMod.create_proxy_class( p_addr, p_port || self.port ) + if p_addr then + ProxyMod.create_proxy_class( p_addr, p_port || self.port ) + else + self + end end alias orig_new new @@ -271,32 +452,34 @@ module Net new( address, port, p_addr, p_port ).start( &block ) end - def proxy_class? - false - end + @is_proxy_class = false + @proxy_addr = nil + @proxy_port = nil - def proxy_address - nil + def proxy_class? + @is_proxy_class end - def proxy_port - nil - end + attr_reader :proxy_address + attr_reader :proxy_port end def proxy? - false + type.proxy? end def proxy_address - nil + type.proxy_address end def proxy_port - nil + type.proxy_port end + alias proxyaddr proxy_address + alias proxyport proxy_port + def edit_path( path ) path end @@ -304,52 +487,22 @@ module Net module ProxyMod - class << self - - def create_proxy_class( p_addr, p_port ) - mod = self - klass = Class.new( HTTP ) - klass.module_eval { - include mod - @proxy_address = p_addr - @proxy_port = p_port - } - def klass.proxy_class? - true - end - - def klass.proxy_address - @proxy_address - end - - def klass.proxy_port - @proxy_port - end - - klass - end - + def self.create_proxy_class( p_addr, p_port ) + mod = self + klass = Class.new( HTTP ) + klass.module_eval { + include mod + @is_proxy = true + @proxy_address = p_addr + @proxy_port = p_port + } + klass end - def initialize( addr, port ) - super - @proxy_address = type.proxy_address - @proxy_port = type.proxy_port - end - - attr_reader :proxy_address, :proxy_port - - alias proxyaddr proxy_address - alias proxyport proxy_port - - def proxy? - true - end - private def conn_socket( addr, port ) - super @proxy_address, @proxy_port + super proxy_address, proxy_port end def edit_path( path ) @@ -363,7 +516,11 @@ module Net # for backward compatibility # - @@newimpl = true + if Version < '1.2.0' then ###noupdate + @@newimpl = false + else + @@newimpl = true + end class << self @@ -375,6 +532,10 @@ module Net @@newimpl = false end + def is_version_1_2? + @@newimpl + end + private def setvar( obj ) @@ -662,15 +823,15 @@ module Net d1 = m[1].to_i d2 = m[2].to_i - if m[1] and m[2] then arr.push (d1 .. d2) - elsif m[1] then arr.push (d1 .. -1) - elsif m[2] then arr.push (-d2 .. -1) + if m[1] and m[2] then arr.push d1..d2 + elsif m[1] then arr.push d1..-1 + elsif m[2] then arr.push -d2..-1 else raise HTTPHeaderSyntaxError, 'range is not specified' end end - return *arr + return arr end def range=( r, fin = nil ) @@ -906,7 +1067,10 @@ module Net @buf.concat s end - alias << write + def <<( s ) + @buf.concat s + self + end def terminate ret = @buf @@ -1028,7 +1192,7 @@ module Net end def value - SuccessCode === self or error! self + SuccessCode === self or error! end @@ -1134,4 +1298,8 @@ module Net } + + HTTPResponse = NetPrivate::HTTPResponse + HTTPResponseReceiver = NetPrivate::HTTPResponse + end # module Net |