diff options
author | aamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-07-08 07:01:22 +0000 |
---|---|---|
committer | aamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-07-08 07:01:22 +0000 |
commit | 9f236c6c605fe451a40e200b8ab75908866b637f (patch) | |
tree | 875d7ce784dca4deb35207be4b31e16e93e90110 /lib | |
parent | 49cc90d6c11f1fc9105901683dc36ccddf7df9d2 (diff) |
aamine
* lib/net/protocol.rb (ProtoSocket#read): modify typo.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@1578 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r-- | lib/net/http.rb | 354 | ||||
-rw-r--r-- | lib/net/pop.rb | 4 | ||||
-rw-r--r-- | lib/net/protocol.rb | 13 | ||||
-rw-r--r-- | lib/net/smtp.rb | 6 |
4 files changed, 204 insertions, 173 deletions
diff --git a/lib/net/http.rb b/lib/net/http.rb index 204d140892..47c3853e6e 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1,6 +1,6 @@ =begin -= net/http.rb version 1.1.35 += net/http.rb version 1.1.36 Copyright (c) 1999-2001 Yukihiro Matsumoto @@ -203,7 +203,7 @@ Yes, this is not thread-safe. : finish finishes HTTP session. - If HTTP session had not started, do nothing and return false. + If HTTP session had not started, raises an IOError. : proxy? true if self is a HTTP proxy class @@ -266,10 +266,7 @@ Yes, this is not thread-safe. 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' + p response['content-type'] : post( path, data, header = nil, dest = '' ) : post( path, data, header = nil ) {|str| .... } @@ -286,71 +283,66 @@ Yes, this is not thread-safe. by "anException.response". # version 1.1 - response, body = http.post( '/index.html', 'querytype=subject&target=ruby' ) + response, body = http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) # version 1.2 - response = http.post( '/index.html', 'querytype=subject&target=ruby' ) + response = http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) # compatible for both version - response , = http.post( '/index.html', 'querytype=subject&target=ruby' ) + response , = http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) # using block File.open( 'save.html', 'w' ) {|f| - http.post( '/index.html', 'querytype=subject&target=ruby' ) do |str| + http.post( '/cgi-bin/search.rb', '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 + http.post '/cgi-bin/search.rb', 'querytype=subject&target=ruby', nil, f } -: request( request [, data] ) -: request( request [, data] ) {|response| .... } - sends a HTTPRequest object 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. +: get2( path, header = nil ) +: get2( path, header = nil ) {|response| .... } + gets entity from PATH. This method returns a HTTPResponse object. - If called with block, gives a HTTPResponse object to the block - with connecting server. + When called with block, keep connection while block is executed + and gives a HTTPResponse object to the block. -== class Net::HTTP::Get, Head, Post + This method never raise any ProtocolErrors. -HTTP request classes. These classes wraps request header and -entity path. All arguments named "key" is case-insensitive. - -=== Class Methods - -: new - creats HTTP request object. - -=== Instance Methods - -: self[ key ] - returns the header field corresponding to the case-insensitive key. - For example, a key of "Content-Type" might return "text/html" - -: self[ key ] = val - sets the header field corresponding to the case-insensitive key. + # example + response = http.get2( '/index.html' ) + p response['content-type'] + puts response.body # body is already read -: each {|name, val| .... } - iterates for each field name and value pair. + # using block + http.get2( '/index.html' ) {|response| + p response['content-type'] + response.read_body do |str| # read body now + print str + end + } -: basic_auth( account, password ) - set Authorization: header for basic auth. +: post2( path, header = nil ) +: post2( path, header = nil ) {|response| .... } + posts data to PATH. This method returns a HTTPResponse object. -: range - returns a Range object which represents Range: header field. + When called with block, gives a HTTPResponse object to the block + before reading entity body, with keeping connection. -: range = r -: set_range( i, len ) - set Range: header from Range (arg r) or beginning index and - length from it (arg i&len). + # example + response = http.post2( '/cgi-bin/nice.rb', 'datadatadata...' ) + p response.status + puts response.body # body is already read -: content_length - returns a Integer object which represents Content-Length: header field. + # using block + http.post2( '/cgi-bin/nice.rb', 'datadatadata...' ) {|response| + p response.status + p response['content-type'] + response.read_body do |str| # read body now + print str + end + } -: content_range - returns a Range object which represents Content-Range: header field. == class Net::HTTPResponse @@ -397,7 +389,6 @@ All arguments named KEY is case-insensitive. response body. If #read_body has been called, this method returns arg of #read_body DEST. Else gets body as String and returns it. - =end require 'net/protocol' @@ -565,7 +556,7 @@ module Net public - def self.def_http_method( nm, hasdest, hasdata ) + def self.define_http_method_interface( nm, hasdest, hasdata ) name = nm.id2name.downcase cname = nm.id2name lineno = __LINE__ + 2 @@ -596,36 +587,46 @@ module Net module_eval src, __FILE__, lineno end - def_http_method :Get, true, false - def_http_method :Head, false, false - def_http_method :Post, true, true - def_http_method :Put, false, true + define_http_method_interface :Get, true, false + define_http_method_interface :Head, false, false + define_http_method_interface :Post, true, true + define_http_method_interface :Put, false, true - def request( req, *args ) - common_oper( req ) { + def request( req, body = nil ) + connecting( req ) { req.__send__( :exec, - @socket, @curr_http_version, edit_path(req.path), *args ) + @socket, @curr_http_version, edit_path(req.path), body ) yield req.response if block_given? } req.response end + def send_request( name, path, body = nil, header = nil ) + r = ::Net::NetPrivate::HTTPGenericRequest.new( + name, (body ? true : false), true, + path, header ) + request r, body + end + private - def common_oper( req ) - req['connection'] ||= 'keep-alive' + def connecting( req ) + unless active? then + implicit = true + req['connection'] ||= 'close' + end + if not @socket then start - req['connection'] = 'close' elsif @socket.closed? then re_connect end if not req.body_exist? or @seems_1_0_server then req['connection'] = 'close' end - req['host'] = addr_port + req['host'] = addr_port() yield req req.response.__send__ :terminate @@ -645,7 +646,9 @@ module Net @socket.close end - req.response + if implicit then + finish + end end def keep_alive?( req, res ) @@ -836,9 +839,9 @@ 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 @@ -915,21 +918,22 @@ module Net end - } - ### ### request ### - net_private { - - class HTTPRequest + class HTTPGenericRequest include ::Net::NetPrivate::HTTPHeader - def initialize( path, uhead = nil ) + def initialize( m, reqbody, resbody, path, uhead = nil ) + @method = m + @request_has_body = reqbody + @response_has_body = resbody @path = path + @response = nil + @header = tmp = {} return unless uhead uhead.each do |k,v| @@ -940,11 +944,9 @@ module Net tmp[ key ] = v.strip end tmp['accept'] ||= '*/*' - - @socket = nil - @response = nil end + attr_reader :method attr_reader :path attr_reader :response @@ -952,10 +954,16 @@ module Net "\#<#{type}>" end - def body_exist? - type::HAS_BODY + def request_body_permitted? + @request_has_body + end + + def response_body_permitted? + @response_has_body end + alias body_exist? response_body_permitted? + private @@ -963,113 +971,92 @@ module Net # write # - def exec( sock, ver, path ) - ready( sock ) { - request ver, path - } - @response - end - - def ready( sock ) - @response = nil - @socket = sock - yield - @response = get_response - @socket = nil - end - - def request( ver, path ) - @socket.writeline sprintf('%s %s HTTP/%s', type::METHOD, path, ver) - canonical_each do |k,v| - @socket.writeline k + ': ' + v + def exec( sock, ver, path, body, &block ) + if body then + check_body_premitted + check_arg_b body, block + sendreq_with_body sock, ver, path, body, &block + else + check_arg_n body + sendreq_no_body sock, ver, path end - @socket.writeline '' + @response = r = get_response( sock ) + r end - # - # read - # - - def get_response - begin - resp = read_response - end while ContinueCode === resp - resp + def check_body_premitted + request_body_permitted? or + raise ArgumentError, 'HTTP request body is not premitted' end - def read_response - resp = get_resline - - while true do - line = @socket.readuntil( "\n", true ) # ignore EOF - line.sub!( /\s+\z/, '' ) # don't use chop! - break if line.empty? - - m = /\A([^:]+):\s*/.match( line ) - m or raise HTTPBadResponse, 'wrong header line format' - nm = m[1] - line = m.post_match - if resp.key? nm then - resp[nm] << ', ' << line - else - resp[nm] = line - end + def check_arg_b( data, block ) + if data and block then + raise ArgumentError, 'both of data and block given' + end + unless data or block then + raise ArgumentError, 'str or block required' end - - resp end - def get_resline - str = @socket.readline - m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/i.match( str ) - m or raise HTTPBadResponse, "wrong status line: #{str}" - httpver = m[1] - status = m[2] - discrip = m[3] - - ::Net::NetPrivate::HTTPResponse.new( - status, discrip, @socket, type::HAS_BODY, httpver ) + def check_arg_n( data ) + data and raise ArgumentError, "data is not permitted for #{@method}" end - - end - - class HTTPRequestWithBody < HTTPRequest - - private - def exec( sock, ver, path, str = nil ) - check_arg str, block_given? + def sendreq_no_body( sock, ver, path ) + request sock, ver, path + end + def sendreq_with_body( sock, ver, path, body ) if block_given? then ac = Accumulator.new yield ac # must be yield, DO NOT USE block.call data = ac.terminate else - data = str + data = body end @header['content-length'] = data.size.to_s @header.delete 'transfer-encoding' - ready( sock ) { - request ver, path - @socket.write data - } - @response + request sock, ver, path + sock.write data end - def check_arg( data, blkp ) - if data and blkp then - raise ArgumentError, 'both of data and block given' - end - unless data or blkp then - raise ArgumentError, 'str or block required' + def request( sock, ver, path ) + sock.writeline sprintf('%s %s HTTP/%s', @method, path, ver) + canonical_each do |k,v| + sock.writeline k + ': ' + v end + sock.writeline '' + end + + # + # read + # + + def get_response( sock ) + begin + resp = ::Net::NetPrivate::HTTPResponse.new_from_socket(sock, + response_body_permitted?) + end while ContinueCode === resp + resp end end + class HTTPRequest < HTTPGenericRequest + + def initialize( path, uhead = nil ) + super type::METHOD, + type::REQUEST_HAS_BODY, + type::RESPONSE_HAS_BODY, + path, uhead + end + + end + + class Accumulator def initialize @@ -1099,23 +1086,27 @@ module Net class HTTP class Get < ::Net::NetPrivate::HTTPRequest - HAS_BODY = true METHOD = 'GET' + REQUEST_HAS_BODY = false + RESPONSE_HAS_BODY = true end class Head < ::Net::NetPrivate::HTTPRequest - HAS_BODY = false METHOD = 'HEAD' + REQUEST_HAS_BODY = false + RESPONSE_HAS_BODY = false end - class Post < ::Net::NetPrivate::HTTPRequestWithBody - HAS_BODY = true + class Post < ::Net::NetPrivate::HTTPRequest METHOD = 'POST' + REQUEST_HAS_BODY = true + RESPONSE_HAS_BODY = true end - class Put < ::Net::NetPrivate::HTTPRequestWithBody - HAS_BODY = true + class Put < ::Net::NetPrivate::HTTPRequest METHOD = 'PUT' + REQUEST_HAS_BODY = true + RESPONSE_HAS_BODY = true end end @@ -1184,6 +1175,45 @@ module Net '505' => HTTPVersionNotSupported } + + class << self + + def new_from_socket( sock, hasbody ) + resp = readnew( sock, hasbody ) + + while true do + line = sock.readuntil( "\n", true ) # ignore EOF + line.sub!( /\s+\z/, '' ) # don't use chop! + break if line.empty? + + m = /\A([^:]+):\s*/.match( line ) + m or raise HTTPBadResponse, 'wrong header line format' + nm = m[1] + line = m.post_match + if resp.key? nm then + resp[nm] << ', ' << line + else + resp[nm] = line + end + end + + resp + end + + private + + def readnew( sock, hasbody ) + str = sock.readline + m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match( str ) + m or raise HTTPBadResponse, "wrong status line: #{str}" + discard, httpv, stat, desc = *m.to_a + + new( stat, desc, sock, hasbody, httpv ) + end + + end + + def initialize( stat, msg, sock, be, hv ) code = CODE_TO_OBJ[stat] || CODE_CLASS_TO_OBJ[stat[0,1]] || diff --git a/lib/net/pop.rb b/lib/net/pop.rb index 9daf68013b..32394acf00 100644 --- a/lib/net/pop.rb +++ b/lib/net/pop.rb @@ -1,6 +1,6 @@ =begin -= net/pop.rb version 1.1.35 += net/pop.rb version 1.1.36 Copyright (c) 1999-2001 Yukihiro Matsumoto @@ -201,7 +201,7 @@ net/pop also supports APOP authentication. There's two way to use APOP: : finish finishes POP3 session. - If POP3 session had not be started, does nothing and return false. + If POP3 session had not be started, raises an IOError. : mails an array of Net::POPMail objects. diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index 28ffab5c72..9504356876 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -1,6 +1,6 @@ =begin -= net/protocol.rb version 1.1.35 += net/protocol.rb version 1.1.36 Copyright (c) 1999-2001 Yukihiro Matsumoto @@ -32,7 +32,7 @@ module Net class Protocol - Version = '1.1.35' + Version = '1.1.36' class << self @@ -122,7 +122,7 @@ module Net # def start( *args ) - return false if active? + active? and raise IOError, 'protocol has been opened already' if block_given? then begin @@ -134,6 +134,7 @@ module Net else _start args end + nil end private @@ -177,12 +178,12 @@ module Net public def finish - return false unless active? + active? or raise IOError, 'already closed protocol' do_finish if @command and not @command.critical? disconnect @active = false - true + nil end private @@ -531,7 +532,7 @@ module Net CRLF = "\r\n" - def read( len, dest = '', ignerr = false ) + def read( len, dest = '', igneof = false ) D_off "reading #{len} bytes..." rsize = 0 diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index d478d927b6..f60cc6edb7 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -1,6 +1,6 @@ =begin -= net/smtp.rb version 1.1.35 += net/smtp.rb version 1.1.36 Copyright (c) 1999-2001 Yukihiro Matsumoto @@ -108,8 +108,8 @@ send or reject SMTP session by this data. : start( helo_domain = <local host name>, account = nil, password = nil, authtype = nil ) : start( helo_domain = <local host name>, account = nil, password = nil, authtype = nil ) {|smtp| .... } opens TCP connection and starts SMTP session. - If protocol had been started, do nothing and return false. HELO_DOMAIN is a domain that you'll dispatch mails from. + If protocol had been started, raises IOError. When this methods is called with block, give a SMTP object to block and close session after block call finished. @@ -141,7 +141,7 @@ send or reject SMTP session by this data. : finish finishes SMTP session. - If SMTP session had not started, do nothing and return false. + If SMTP session had not started, raises an IOError. : send_mail( mailsrc, from_addr, *to_addrs ) This method sends MAILSRC as mail. A SMTP object read strings |