aamine
* lib/net/http.rb: can call {old,new}_implementation any times. * lib/net/http.rb: HTTP#connecting, receive -> common_oper, connecting. * lib/net/http.rb: output warning if u_header includes duplicated header. * lib/net/http.rb: not check Connection:/Proxy-Connection; always read until eof. * lib/net/protocol: detects and catches "break" from block. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1041 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
074203d270
commit
0d11c322d1
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
|||||||
|
Thu Nov 16 23:06:07 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
||||||
|
|
||||||
|
* lib/net/http.rb: can call {old,new}_implementation any times.
|
||||||
|
|
||||||
|
* lib/net/http.rb: HTTP#connecting, receive ->
|
||||||
|
common_oper, connecting.
|
||||||
|
|
||||||
|
* lib/net/http.rb: output warning if u_header includes
|
||||||
|
duplicated header.
|
||||||
|
|
||||||
|
* lib/net/http.rb: not check Connection:/Proxy-Connection;
|
||||||
|
always read until eof.
|
||||||
|
|
||||||
|
* lib/net/protocol: detects and catches "break" from block.
|
||||||
|
|
||||||
Thu Nov 16 14:58:00 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
Thu Nov 16 14:58:00 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
||||||
|
|
||||||
* ext/socket/socket.c (sock_new): duplicates file descriptor
|
* ext/socket/socket.c (sock_new): duplicates file descriptor
|
||||||
|
229
lib/net/http.rb
229
lib/net/http.rb
@ -20,12 +20,13 @@ You can get it from RAA
|
|||||||
|
|
||||||
: new( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
|
: new( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
|
||||||
creates a new Net::HTTP object.
|
creates a new Net::HTTP object.
|
||||||
if proxy_addr is given, this method is equals to
|
If proxy_addr is given, this method is equals to
|
||||||
Net::HTTP::Proxy(proxy_addr,proxy_port).
|
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 )
|
||||||
: start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil ) {|http| .... }
|
: 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)
|
is equals to
|
||||||
|
Net::HTTP.new( address, port, proxy_addr, proxy_port ).start(&block)
|
||||||
|
|
||||||
: Proxy( address, port )
|
: Proxy( address, port )
|
||||||
creates a HTTP proxy class.
|
creates a HTTP proxy class.
|
||||||
@ -86,15 +87,15 @@ You can get it from RAA
|
|||||||
# example
|
# example
|
||||||
begin
|
begin
|
||||||
response, body = http.get( '/index.html' )
|
response, body = http.get( '/index.html' )
|
||||||
rescue Net::ProtoRetriableError
|
rescue Net::ProtoRetriableError => err
|
||||||
response = $!.data
|
response = err.data
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
|
|
||||||
: head( path, header = nil )
|
: head( path, header = nil )
|
||||||
get only header from "path" on connecting host.
|
gets only header from "path" on connecting host.
|
||||||
"header" is a Hash like { 'Accept' => '*/*', ... }.
|
"header" is a Hash like { 'Accept' => '*/*', ... }.
|
||||||
This method returns Net::HTTPResponse object.
|
This method returns a Net::HTTPResponse object.
|
||||||
You can http header from this object like:
|
You can http header from this object like:
|
||||||
|
|
||||||
response['content-length'] #-> '2554'
|
response['content-length'] #-> '2554'
|
||||||
@ -104,13 +105,13 @@ You can get it from RAA
|
|||||||
|
|
||||||
: post( path, data, header = nil, dest = '' )
|
: post( path, data, header = nil, dest = '' )
|
||||||
: post( path, data, header = nil ) {|str| .... }
|
: post( path, data, header = nil ) {|str| .... }
|
||||||
post "data"(must be String now) to "path".
|
posts "data" (must be String now) to "path".
|
||||||
If body exists, also get entity body.
|
If the body exists, also gets entity body.
|
||||||
It is written to "dest" by using "<<" method.
|
Data is written to "dest" by using "<<" method.
|
||||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||||
This method returns Net::HTTPResponse object and "dest".
|
This method returns Net::HTTPResponse object and "dest".
|
||||||
|
|
||||||
If called with block, gives a part String of entity body.
|
If called with block, gives a part of entity body string.
|
||||||
|
|
||||||
: get2( path, header = nil )
|
: get2( path, header = nil )
|
||||||
: get2( path, header = nil ) {|recv| .... }
|
: get2( path, header = nil ) {|recv| .... }
|
||||||
@ -145,7 +146,7 @@ You can get it from RAA
|
|||||||
: head2( path, header = nil )
|
: head2( path, header = nil )
|
||||||
: head2( path, header = nil ) {|recv| .... }
|
: head2( path, header = nil ) {|recv| .... }
|
||||||
send HEAD request for "path".
|
send HEAD request for "path".
|
||||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
"header" must be a Hash like { 'Accept' => 'text/html', ... }.
|
||||||
The difference between "head" method is that
|
The difference between "head" method is that
|
||||||
"head2" does not raise exceptions.
|
"head2" does not raise exceptions.
|
||||||
|
|
||||||
@ -162,7 +163,7 @@ You can get it from RAA
|
|||||||
|
|
||||||
: post2( path, data, header = nil )
|
: post2( path, data, header = nil )
|
||||||
: post2( path, data, header = nil ) {|recv| .... }
|
: post2( path, data, header = nil ) {|recv| .... }
|
||||||
post "data"(must be String now) to "path".
|
posts "data" (must be String now) to "path".
|
||||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||||
If this method is called with block, one gives
|
If this method is called with block, one gives
|
||||||
a HTTPResponseReceiver object to block.
|
a HTTPResponseReceiver object to block.
|
||||||
@ -200,10 +201,10 @@ All "key" is case-insensitive.
|
|||||||
set field value for "key".
|
set field value for "key".
|
||||||
|
|
||||||
: key?( key )
|
: key?( key )
|
||||||
true if key is exist
|
true if key exists
|
||||||
|
|
||||||
: each {|name,value| .... }
|
: each {|name,value| .... }
|
||||||
iterate for each field name and value pair
|
iterates for each field name and value pair
|
||||||
|
|
||||||
: code
|
: code
|
||||||
HTTP result code string. For example, '302'
|
HTTP result code string. For example, '302'
|
||||||
@ -232,33 +233,33 @@ All "key" is case-insensitive.
|
|||||||
|
|
||||||
= http.rb version 1.2 features
|
= http.rb version 1.2 features
|
||||||
|
|
||||||
You can use these 1.2 features by calling method
|
You can use 1.2 features by calling HTTP.new_implementation. And
|
||||||
Net::HTTP.new_implementation. Or you want to use 1.1 feature,
|
calling Net::HTTP.old_implementation allows to use 1.1 features.
|
||||||
call Net::HTTP.old_implementation.
|
|
||||||
|
|
||||||
Now old_impl is default and if new_impl was called then Net::HTTP
|
# example
|
||||||
changes self into new implementation. In 1.2, new_impl is default
|
HTTP.start {|http1| ...(http1 has 1.1 features)... }
|
||||||
and if old_impl was called then changes self into old implementation.
|
|
||||||
|
|
||||||
== Warning!!!
|
HTTP.new_implementation
|
||||||
|
HTTP.start {|http2| ...(http2 has 1.2 features)... }
|
||||||
|
|
||||||
You can call new_implementation/old_implementation any times
|
HTTP.old_implementation
|
||||||
but CANNOT call both of them at the same time.
|
HTTP.start {|http3| ...(http3 has 1.1 features)... }
|
||||||
You must use one implementation in one application (process).
|
|
||||||
|
|
||||||
== Method
|
== Method (only diff to 1.1)
|
||||||
|
|
||||||
: get( path, u_header = nil )
|
: get( path, u_header = nil )
|
||||||
: get( path, u_header = nil ) {|str| .... }
|
: get( path, u_header = nil ) {|str| .... }
|
||||||
get document from "path" and returns HTTPResponse object.
|
gets document from "path".
|
||||||
|
returns HTTPResponse object.
|
||||||
|
|
||||||
: head( path, u_header = nil )
|
: head( path, u_header = nil )
|
||||||
get only document header from "path" and returns HTTPResponse object.
|
gets only document header from "path".
|
||||||
|
returns HTTPResponse object.
|
||||||
|
|
||||||
: post( path, data, u_header = nil )
|
: post( path, data, u_header = nil )
|
||||||
: post( path, data, u_header = nil ) {|str| .... }
|
: post( path, data, u_header = nil ) {|str| .... }
|
||||||
post "data" to "path" entity and get document,
|
posts "data" to "path" entity and gets document.
|
||||||
then returns HTTPResponse object.
|
returns HTTPResponse object.
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
@ -290,7 +291,10 @@ module Net
|
|||||||
alias orig_new new
|
alias orig_new new
|
||||||
|
|
||||||
def new( address = nil, port = nil, p_addr = nil, p_port = nil )
|
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 )
|
c = p_addr ? self::Proxy(p_addr, p_port) : self
|
||||||
|
i = c.orig_new( address, port )
|
||||||
|
setvar i
|
||||||
|
i
|
||||||
end
|
end
|
||||||
|
|
||||||
def start( address = nil, port = nil, p_addr = nil, p_port = nil, &block )
|
def start( address = nil, port = nil, p_addr = nil, p_port = nil, &block )
|
||||||
@ -332,47 +336,26 @@ module Net
|
|||||||
### 1.2 implementation
|
### 1.2 implementation
|
||||||
###
|
###
|
||||||
|
|
||||||
@new_impl = false
|
@@newimpl = false
|
||||||
|
|
||||||
class << self
|
#class << self
|
||||||
|
|
||||||
def new_implementation
|
def self.new_implementation
|
||||||
return if @new_impl
|
@@newimpl = true
|
||||||
@new_impl = true
|
|
||||||
module_eval %^
|
|
||||||
|
|
||||||
undef head
|
|
||||||
alias head head2
|
|
||||||
|
|
||||||
undef get
|
|
||||||
|
|
||||||
def get( path, u_header = nil, dest = nil, &block )
|
|
||||||
get2( path, u_header ) {|f| f.body( dest, &block ) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
undef post
|
def self.old_implementation
|
||||||
|
@@newimpl = false
|
||||||
def post( path, data, u_header = nil, dest = nil, &block )
|
|
||||||
post2( path, data, u_header ) {|f| f.body( dest, &block ) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
undef put
|
#private
|
||||||
|
|
||||||
def put( path, src, u_header = nil )
|
def self.setvar( obj )
|
||||||
put2( path, src, u_header ) {|f| f.body }
|
f = @@newimpl
|
||||||
|
obj.instance_eval { @newimpl = f }
|
||||||
end
|
end
|
||||||
|
|
||||||
^
|
#end
|
||||||
end
|
|
||||||
|
|
||||||
def old_implementation
|
|
||||||
if @new_impl then
|
|
||||||
raise RuntimeError,
|
|
||||||
'http.rb is already switched to new implementation'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
@ -381,42 +364,49 @@ module Net
|
|||||||
|
|
||||||
def get( path, u_header = nil, dest = nil, &block )
|
def get( path, u_header = nil, dest = nil, &block )
|
||||||
resp = get2( path, u_header ) {|f| f.body( dest, &block ) }
|
resp = get2( path, u_header ) {|f| f.body( dest, &block ) }
|
||||||
|
if @newimpl then
|
||||||
|
resp
|
||||||
|
else
|
||||||
resp.value
|
resp.value
|
||||||
return resp, resp.body
|
return resp, resp.body
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get2( path, u_header = nil, &block )
|
def get2( path, u_header = nil, &block )
|
||||||
connecting( u_header ) {|uh|
|
common_oper( u_header, true, block ) {|uh|
|
||||||
@command.get edit_path(path), uh
|
@command.get edit_path(path), uh
|
||||||
receive true, block
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def head( path, u_header = nil )
|
def head( path, u_header = nil )
|
||||||
resp = head2( path, u_header )
|
resp = head2( path, u_header )
|
||||||
|
unless @newimpl then
|
||||||
resp.value
|
resp.value
|
||||||
|
end
|
||||||
resp
|
resp
|
||||||
end
|
end
|
||||||
|
|
||||||
def head2( path, u_header = nil, &block )
|
def head2( path, u_header = nil, &block )
|
||||||
connecting( u_header ) {|uh|
|
common_oper( u_header, false, block ) {|uh|
|
||||||
@command.head edit_path(path), uh
|
@command.head edit_path(path), uh
|
||||||
receive false, block
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def post( path, data, u_header = nil, dest = nil, &block )
|
def post( path, data, u_header = nil, dest = nil, &block )
|
||||||
resp = post2( path, data, u_header ) {|f| f.body( dest, &block ) }
|
resp = post2( path, data, u_header ) {|f| f.body( dest, &block ) }
|
||||||
|
if @newimpl then
|
||||||
|
resp
|
||||||
|
else
|
||||||
resp.value
|
resp.value
|
||||||
return resp, resp.body
|
return resp, resp.body
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def post2( path, data, u_header = nil, &block )
|
def post2( path, data, u_header = nil, &block )
|
||||||
connecting( u_header ) {|uh|
|
common_oper( u_header, true, block ) {|uh|
|
||||||
@command.post edit_path(path), uh, data
|
@command.post edit_path(path), uh, data
|
||||||
receive true, block
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -424,14 +414,17 @@ module Net
|
|||||||
# not tested because I could not setup apache (__;;;
|
# not tested because I could not setup apache (__;;;
|
||||||
def put( path, src, u_header = nil )
|
def put( path, src, u_header = nil )
|
||||||
resp = put2( path, src, u_header ) {|f| f.body }
|
resp = put2( path, src, u_header ) {|f| f.body }
|
||||||
|
if @newimpl then
|
||||||
|
resp
|
||||||
|
else
|
||||||
resp.value
|
resp.value
|
||||||
return resp, resp.body
|
return resp, resp.body
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def put2( path, src, u_header = nil, &block )
|
def put2( path, src, u_header = nil, &block )
|
||||||
connecting( u_header ) {|uh|
|
common_oper( u_header, true, block ) {|uh|
|
||||||
@command.put path, uh, src
|
@command.put path, uh, src
|
||||||
receive true, block
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -439,8 +432,28 @@ module Net
|
|||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
def connecting( u_header )
|
def common_oper( u_header, body_exist, block )
|
||||||
u_header = procheader( u_header )
|
u_header = procheader( u_header )
|
||||||
|
recv = err = nil
|
||||||
|
|
||||||
|
connecting( u_header ) {
|
||||||
|
recv = HTTPResponseReceiver.new( @command, body_exist )
|
||||||
|
yield u_header
|
||||||
|
begin
|
||||||
|
block.call recv if block
|
||||||
|
rescue Exception => err
|
||||||
|
;
|
||||||
|
end
|
||||||
|
recv.terminate
|
||||||
|
|
||||||
|
recv.response
|
||||||
|
}
|
||||||
|
raise err if err
|
||||||
|
|
||||||
|
recv.response
|
||||||
|
end
|
||||||
|
|
||||||
|
def connecting( u_header )
|
||||||
if not @socket then
|
if not @socket then
|
||||||
u_header['Connection'] = 'close'
|
u_header['Connection'] = 'close'
|
||||||
start
|
start
|
||||||
@ -448,13 +461,11 @@ module Net
|
|||||||
@socket.reopen
|
@socket.reopen
|
||||||
end
|
end
|
||||||
|
|
||||||
resp = yield( u_header )
|
resp = yield
|
||||||
|
|
||||||
unless keep_alive? u_header, resp then
|
unless keep_alive? u_header, resp then
|
||||||
@socket.close
|
@socket.close
|
||||||
end
|
end
|
||||||
|
|
||||||
resp
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def keep_alive?( header, resp )
|
def keep_alive?( header, resp )
|
||||||
@ -487,24 +498,20 @@ module Net
|
|||||||
ret[ 'Accept' ] = '*/*'
|
ret[ 'Accept' ] = '*/*'
|
||||||
|
|
||||||
return ret unless h
|
return ret unless h
|
||||||
|
tmp = {}
|
||||||
h.each do |k,v|
|
h.each do |k,v|
|
||||||
arr = k.split('-')
|
key = k.split('-').collect {|i| i.capitalize }.join('-')
|
||||||
arr.each {|i| i.capitalize! }
|
if tmp[key] then
|
||||||
ret[ arr.join('-') ] = v
|
$stderr.puts "'#{key}' http header appered twice" if $VERBOSE
|
||||||
end
|
end
|
||||||
|
tmp[key] = v
|
||||||
|
end
|
||||||
|
ret.update tmp
|
||||||
|
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def receive( body_exist, block )
|
|
||||||
recv = HTTPResponseReceiver.new( @command, body_exist )
|
|
||||||
block.call recv if block
|
|
||||||
recv.terminate
|
|
||||||
recv.header
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# called when connecting
|
# called when connecting
|
||||||
def do_finish
|
def do_finish
|
||||||
unless @socket.closed? then
|
unless @socket.closed? then
|
||||||
@ -600,29 +607,31 @@ module Net
|
|||||||
alias header read_header
|
alias header read_header
|
||||||
alias response read_header
|
alias response read_header
|
||||||
|
|
||||||
def body( dest = nil, &block )
|
def read_body( dest = nil, &block )
|
||||||
unless @body then
|
unless @body then
|
||||||
self.read_header
|
read_header
|
||||||
|
|
||||||
to = procdest( dest, block )
|
to = procdest( dest, block )
|
||||||
stream_check
|
stream_check
|
||||||
if @body_exist and header.code_type.body_exist? then
|
|
||||||
@command.get_body header, to
|
if @body_exist and @header.code_type.body_exist? then
|
||||||
header.body = @body = to
|
@command.get_body @header, to
|
||||||
|
@header.body = @body = to
|
||||||
else
|
else
|
||||||
@command.no_body
|
@command.no_body
|
||||||
header.body = nil
|
@header.body = nil
|
||||||
@body = 1
|
@body = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@body == 1 ? nil : @body
|
@body == 1 ? nil : @body
|
||||||
end
|
end
|
||||||
|
|
||||||
alias entity body
|
alias body read_body
|
||||||
|
alias entity read_body
|
||||||
|
|
||||||
def terminate
|
def terminate
|
||||||
header
|
read_header
|
||||||
body
|
read_body
|
||||||
@command = nil
|
@command = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -955,7 +964,7 @@ module Net
|
|||||||
|
|
||||||
def get_body( resp, dest )
|
def get_body( resp, dest )
|
||||||
if chunked? resp then
|
if chunked? resp then
|
||||||
read_chunked( dest, resp )
|
read_chunked dest
|
||||||
else
|
else
|
||||||
clen = content_length( resp )
|
clen = content_length( resp )
|
||||||
if clen then
|
if clen then
|
||||||
@ -965,15 +974,7 @@ module Net
|
|||||||
if clen then
|
if clen then
|
||||||
@socket.read clen, dest
|
@socket.read clen, dest
|
||||||
else
|
else
|
||||||
tmp = resp['connection']
|
|
||||||
if tmp and /close/i === tmp then
|
|
||||||
@socket.read_all dest
|
@socket.read_all dest
|
||||||
else
|
|
||||||
tmp = resp['proxy-connection']
|
|
||||||
if tmp and /close/i === tmp then
|
|
||||||
@socket.read_all dest
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -987,7 +988,7 @@ module Net
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def read_chunked( ret, header )
|
def read_chunked( dest )
|
||||||
len = nil
|
len = nil
|
||||||
total = 0
|
total = 0
|
||||||
|
|
||||||
@ -999,7 +1000,7 @@ module Net
|
|||||||
end
|
end
|
||||||
len = m[0].hex
|
len = m[0].hex
|
||||||
break if len == 0
|
break if len == 0
|
||||||
@socket.read( len, ret ); total += len
|
@socket.read( len, dest ); total += len
|
||||||
@socket.read 2 # \r\n
|
@socket.read 2 # \r\n
|
||||||
end
|
end
|
||||||
until @socket.readline.empty? do
|
until @socket.readline.empty? do
|
||||||
@ -1007,9 +1008,9 @@ module Net
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def content_length( header )
|
def content_length( resp )
|
||||||
if header.key? 'content-length' then
|
if resp.key? 'content-length' then
|
||||||
m = /\d+/.match( header['content-length'] )
|
m = /\d+/.match( resp['content-length'] )
|
||||||
unless m then
|
unless m then
|
||||||
raise HTTPBadResponse, 'wrong Content-Length format'
|
raise HTTPBadResponse, 'wrong Content-Length format'
|
||||||
end
|
end
|
||||||
@ -1019,14 +1020,14 @@ module Net
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def chunked?( header )
|
def chunked?( resp )
|
||||||
str = header[ 'transfer-encoding' ]
|
tmp = resp['transfer-encoding']
|
||||||
str and /(?:\A|\s+)chunked(?:\s+|\z)/i === str
|
tmp and /(?:\A|\s+)chunked(?:\s+|\z)/i === tmp
|
||||||
end
|
end
|
||||||
|
|
||||||
def range_length( header )
|
def range_length( resp )
|
||||||
if header.key? 'content-range' then
|
if resp.key? 'content-range' then
|
||||||
m = %r<bytes\s+(\d+)-(\d+)/\d+>.match( header['content-range'] )
|
m = %r<bytes\s+(\d+)-(\d+)/\d+>.match( resp['content-range'] )
|
||||||
unless m then
|
unless m then
|
||||||
raise HTTPBadResponse, 'wrong Content-Range format'
|
raise HTTPBadResponse, 'wrong Content-Range format'
|
||||||
end
|
end
|
||||||
|
@ -314,12 +314,31 @@ module Net
|
|||||||
end
|
end
|
||||||
|
|
||||||
def <<( str )
|
def <<( str )
|
||||||
@block.call str
|
callblock( str, &@block ) if @block
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def callblock( str )
|
||||||
|
begin
|
||||||
|
user_break = true
|
||||||
|
yield str
|
||||||
|
user_break = false
|
||||||
|
rescue Exception
|
||||||
|
user_break = false
|
||||||
|
raise
|
||||||
|
ensure
|
||||||
|
if user_break then
|
||||||
|
@block = nil
|
||||||
|
return # stop break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Command
|
class Command
|
||||||
|
|
||||||
def initialize( sock )
|
def initialize( sock )
|
||||||
@ -442,6 +461,7 @@ module Net
|
|||||||
def address
|
def address
|
||||||
@addr.dup
|
@addr.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
alias addr address
|
alias addr address
|
||||||
|
|
||||||
attr_reader :port
|
attr_reader :port
|
||||||
@ -449,11 +469,16 @@ module Net
|
|||||||
def ip_address
|
def ip_address
|
||||||
@ipaddr.dup
|
@ipaddr.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
alias ipaddr ip_address
|
alias ipaddr ip_address
|
||||||
|
|
||||||
attr_reader :sending
|
attr_reader :sending
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### read
|
||||||
|
###
|
||||||
|
|
||||||
CRLF = "\r\n"
|
CRLF = "\r\n"
|
||||||
|
|
||||||
def read( len, dest = '' )
|
def read( len, dest = '' )
|
||||||
@ -514,7 +539,7 @@ module Net
|
|||||||
|
|
||||||
rsize = 0
|
rsize = 0
|
||||||
|
|
||||||
while (str = readuntil( "\r\n" )) != ".\r\n" do
|
while (str = readuntil("\r\n")) != ".\r\n" do
|
||||||
rsize += str.size
|
rsize += str.size
|
||||||
str.gsub!( /\A\./, '' )
|
str.gsub!( /\A\./, '' )
|
||||||
dest << str
|
dest << str
|
||||||
@ -525,20 +550,19 @@ module Net
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# private use only (can not handle 'break')
|
||||||
def read_pendlist
|
def read_pendlist
|
||||||
@pipe << "reading list...\n" if @pipe; pipeoff
|
@pipe << "reading list...\n" if @pipe; pipeoff
|
||||||
|
|
||||||
arr = []
|
|
||||||
str = nil
|
str = nil
|
||||||
|
i = 0
|
||||||
while (str = readuntil( "\r\n" )) != ".\r\n" do
|
while (str = readuntil("\r\n")) != ".\r\n" do
|
||||||
str.chop!
|
str.chop!
|
||||||
arr.push str
|
yield str
|
||||||
yield str if block_given?
|
i += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@pipe << "read #{arr.size} lines\n" if pipeon
|
@pipe << "read #{i} items\n" if pipeon
|
||||||
arr
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -561,6 +585,10 @@ module Net
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### write
|
||||||
|
###
|
||||||
|
|
||||||
public
|
public
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user