diff options
-rw-r--r-- | lib/net/http.rb | 129 | ||||
-rw-r--r-- | lib/net/protocol.rb | 157 |
2 files changed, 192 insertions, 94 deletions
diff --git a/lib/net/http.rb b/lib/net/http.rb index 40f6238d50..c5612c8754 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -13,12 +13,14 @@ You can freely distribute/modify this library. == Class Methods -: new( address = 'localhost', port = 80 ) +: 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). -: start( address = 'localhost', port = 80 ) -: start( address = 'localhost', port = 80 ) {|http| .... } - equals to Net::HTTP.new( address, port ).start +: 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 Net::HTTP.new( address, port, proxy_addr, proxy_port ).start(&block) : port HTTP default port, 80 @@ -127,11 +129,8 @@ All "key" is case-insensitive. == Methods -: code - HTTP result code. For example, '302' - -: message - HTTP result message. For example, 'Not Found' +: body + the entity body. ("dest" argument for HTTP#get, post, put) : self[ key ] returns header field for "key". @@ -148,9 +147,11 @@ All "key" is case-insensitive. : each {|name,value| .... } iterate for each field name and value pair -: body - "dest" argument for HTTP#get, post, put +: code + HTTP result code. For example, '302' +: message + HTTP result message. For example, 'Not Found' = class HTTPReadAdapter @@ -169,6 +170,37 @@ All "key" is case-insensitive. If this method is called twice, block is not called and returns first "dest". + += http.rb version 1.2 features + +You can use these 1.2 features by calling method +Net::HTTP.new_implementation. Or you want to use 1.1 feature, +call Net::HTTP.old_implementation. + +Now old_impl is default and if new_impl was called then Net::HTTP +changes self into new implementation. In 1.2, new_impl is default +and if old_impl was called then changes self into old implementation. + +== Warning!!! + +You can call new_implementation/old_implementation any times +but CANNOT call both of them at the same time. +You must use one implementation in one application (process). + +== Method + +: get( path, u_header = nil ) +: get( path, u_header = nil ) {|str| .... } +get document from "path" and returns HTTPResponse object. + +: head( path, u_header = nil ) +get only document header from "path" and returns HTTPResponse object. + +: post( path, data, u_header = nil ) +: post( path, data, u_header = nil ) {|str| .... } +post "data" to "path" entity and get document, +then returns HTTPResponse object. + =end require 'net/protocol' @@ -184,15 +216,73 @@ module Net protocol_param :port, '80' protocol_param :command_type, '::Net::HTTPCommand' - def HTTP.procdest( dest, block ) - if block then - return ReadAdapter.new( block ), nil - else - dest ||= '' - return dest, dest + class << self + + def procdest( dest, block ) + if block then + return ReadAdapter.new( block ), nil + else + dest ||= '' + return dest, dest + end + end + + alias orig_new new + + def new( address = nil, port = nil, p_addr = nil, p_port = nil ) + (p_addr ? self::Proxy(p_addr, p_port) : self).orig_new( address, port ) + end + + def start( address = nil, port = nil, p_addr = nil, p_port = nil, &block ) + new( address, port, p_addr, p_port ).start( &block ) + end + + end + + @new_impl = false + + def HTTP.new_implementation + return if @new_impl + @new_impl = true + module_eval %^ + + undef head + alias head head2 + undef head2 + + alias old_get2 get2 + undef get2 + undef get + + def get( path, u_header = nil, dest = nil, &block ) + old_get2( path, u_header ) {|f| f.body( dest, &block ) } + end + + alias old_post2 post2 + undef post2 + undef post + + def post( path, data, u_header = nil, dest = nil, &block ) + old_post2( path, data, u_header ) {|f| f.body( dest, &block ) } + end + + alias old_put2 put2 + undef put2 + undef put + + def put( path, src, u_header = nil ) + old_put2( path, src, u_header ) {|f| f.body } end + + ^ end + def HTTP.old_implementation + if @new_impl then + raise RuntimeError, "http.rb is already switched to new implementation" + end + end + def get( path, u_header = nil, dest = nil, &block ) resp = get2( path, u_header ) {|f| dest = f.body( dest, &block ) } @@ -237,10 +327,9 @@ module Net # not tested because I could not setup apache (__;;; def put( path, src, u_header = nil ) - ret = nil - resp = put2( path, src, u_header ) {|f| ret = f.body } + resp = put2( path, src, u_header ) {|f| f.body } resp.value - return resp, ret + return resp, resp.body end def put2( path, src, u_header = nil, &block ) diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index 25b41932f1..f234371a69 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -64,7 +64,7 @@ module Net class Protocol - Version = '1.1.23' + Version = '1.1.24' class << self @@ -80,7 +80,8 @@ module Net end end - def Proxy( p_addr, p_port ) + def Proxy( p_addr, p_port = nil ) + p_port ||= self.port klass = Class.new( self ) klass.module_eval %- @@ -109,7 +110,7 @@ module Net def proxy? false end - + private @@ -587,44 +588,43 @@ module Net def write( str ) - do_write_beg - do_write_do str - do_write_fin + writing { + do_write str + } end def writeline( str ) - do_write_beg - do_write_do str - do_write_do "\r\n" - do_write_fin + writing { + do_write str + do_write "\r\n" + } end def write_bin( src, block ) - do_write_beg - if block then - block.call WriteAdapter.new( self, :do_write_do ) - else - src.each do |bin| - do_write_do bin + writing { + if block then + block.call WriteAdapter.new( self, :do_write ) + else + src.each do |bin| + do_write bin + end end - end - do_write_fin + } end def write_pendstr( src, block ) @pipe << "writing text from #{src.type}\n" if @pipe; pipeoff - do_write_beg - if block then - block.call WriteAdapter.new( self, :write_pendstr_inner ) - else - write_pendstr_inner src - end - do_write_do ".\r\n" - wsize = do_write_fin + wsize = use_each_crlf_line { + if block then + block.call WriteAdapter.new( self, :wpend_in ) + else + wpend_in src + end + } @pipe << "wrote #{wsize} bytes text\n" if pipeon wsize @@ -634,82 +634,102 @@ module Net private - def write_inner( src ) - each_crlf_line( src, :do_write_do ) + def wpend_in( src ) + line = nil + each_crlf_line( src ) do |line| + do_write '.' if line[0] == ?. + do_write line + end end + def use_each_crlf_line + writing { + @wbuf = '' - def write_pendstr_inner( src ) - each_crlf_line src, :i_w_pend - end + yield - def i_w_pend( line ) - do_write_do '.' if line[0] == ?. - do_write_do line - end + if not @wbuf.empty? then # un-terminated last line + if @wbuf[-1] == ?\r then + @wbuf.chop! + end + @wbuf.concat "\r\n" + do_write @wbuf + elsif @writtensize == 0 then # empty src + do_write "\r\n" + end + do_write ".\r\n" + @wbuf = nil + } + end - def each_crlf_line( src, mid ) - buf = '' + def each_crlf_line( src ) str = m = nil + beg = 0 - adding( src, buf ) do - while true do - m = /[^\r\n]*(\n|\r\n|\r)/.match( buf ) - break unless m - - str = m[0] - if str.size == buf.size and buf[-1] == ?\r then + adding( src ) do + buf = @wbuf + while buf.index( /\n|\r\n|\r/, beg ) do + m = $~ + if m.begin(0) == buf.size - 1 and buf[-1] == ?\r then # "...\r" : can follow "\n..." break end - buf[ 0, str.size ] = '' - str.chop! + str = buf[ beg, m.begin(0) - beg ] str.concat "\r\n" - __send__ mid, str + yield str + beg = m.end(0) end - end - if not buf.empty? then # un-terminated last line - buf.concat "\r\n" - __send__ mid, buf - elsif not str then # empty src - __send__ mid, "\r\n" + @wbuf = buf[ beg, buf.size - beg ] end end - def adding( src, buf ) + def adding( src ) i = nil case src when String - 0.step( src.size, 512 ) do |i| - buf << src[ i, 512 ] + 0.step( src.size - 1, 2048 ) do |i| + @wbuf << src[i,2048] yield end when File while true do - i = src.read( 512 ) + i = src.read( 2048 ) break unless i - buf << i + i[0,0] = @wbuf + @wbuf = i yield end else - src.each do |bin| - buf << bin - yield if buf.size > 512 + src.each do |i| + @wbuf << i + if @wbuf.size > 2048 then + yield + end end end end - def do_write_beg + def writing @writtensize = 0 @sending = '' + + yield + + if @pipe then + @pipe << 'write "' + @pipe << @sending + @pipe << "\"\n" + end + @socket.flush + @writtensize end - def do_write_do( arg ) + def do_write( arg ) if @pipe or @sending.size < 128 then @sending << Net.quote( arg ) else @@ -721,17 +741,6 @@ module Net s end - def do_write_fin - if @pipe then - @pipe << 'write "' - @pipe << @sending - @pipe << "\"\n" - end - - @socket.flush - @writtensize - end - def pipeoff @prepipe = @pipe |