From fa20d931bcd07a5f7d8ab80edc79419cae1d25fd Mon Sep 17 00:00:00 2001 From: aamine Date: Tue, 3 Jul 2001 18:13:13 +0000 Subject: aamine * lib/net/http.rb: new method HTTP#request_by_name (test) * lib/net/http.rb: new class HTTPGenericRequest git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1564 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/net/http.rb | 252 +++++++++++++++++++++++++++++----------------------- lib/net/pop.rb | 2 +- lib/net/protocol.rb | 4 +- lib/net/smtp.rb | 2 +- 4 files changed, 146 insertions(+), 114 deletions(-) (limited to 'lib/net') diff --git a/lib/net/http.rb b/lib/net/http.rb index afa58ea711..f0c7dbff6c 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1,6 +1,6 @@ =begin -= net/http.rb version 1.2.1 += net/http.rb version 1.2.2 Copyright (c) 1999-2001 Yukihiro Matsumoto @@ -565,7 +565,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,25 +596,32 @@ 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 request_by_name( name, path, header, body = nil ) + r = ::Net::NetPrivate::HTTPGenericRequest.new( + name, body ? true : false, true, + path, header ) + request r, body + end + private - def common_oper( req ) + def connecting( req ) req['connection'] ||= 'keep-alive' if not @socket then start @@ -644,8 +651,6 @@ module Net D 'Conn close' @socket.close end - - req.response end def keep_alive?( req, res ) @@ -836,9 +841,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 +920,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 +946,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 +956,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 +973,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 +1088,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 +1177,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 806cae7775..49751a1923 100644 --- a/lib/net/pop.rb +++ b/lib/net/pop.rb @@ -1,6 +1,6 @@ =begin -= net/pop.rb version 1.2.1 += net/pop.rb version 1.2.2 Copyright (c) 1999-2001 Yukihiro Matsumoto diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index 52c4926d43..d810ac2f9d 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -1,6 +1,6 @@ =begin -= net/protocol.rb version 1.2.1 += net/protocol.rb version 1.2.2 Copyright (c) 1999-2001 Yukihiro Matsumoto @@ -32,7 +32,7 @@ module Net class Protocol - Version = '1.2.1' + Version = '1.2.2' class << self diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index a908edcf7d..c56d2c9e32 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -1,6 +1,6 @@ =begin -= net/smtp.rb version 1.2.1 += net/smtp.rb version 1.2.2 Copyright (c) 1999-2001 Yukihiro Matsumoto -- cgit v1.2.3