* lib/net/http.rb: always close connection on request without body.
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: change copyright.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1212 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 2001-02-24 04:53:50 +00:00
parent acce0b7ec4
commit b1cd5105d4
5 changed files with 164 additions and 125 deletions

View File

@ -1,3 +1,10 @@
Sat Feb 24 13:58:48 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
* lib/net/http.rb: always close connection on request without
body.
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: change copyright.
Fri Feb 23 08:28:58 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp> Fri Feb 23 08:28:58 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
* lib/net/protocol.rb: clear read buffer after reopen. * lib/net/protocol.rb: clear read buffer after reopen.

View File

@ -2,21 +2,23 @@
= net/http.rb version 1.2.0 = net/http.rb version 1.2.0
maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp> 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". This file is derived from "http-access.rb".
This program is free software. This program is free software. You can re-distribute and/or
You can distribute/modify this program under modify this program under the same terms as Ruby itself,
the terms of the Ruby Distribute License. GNU General Public License or Ruby License.
Japanese version of this document is in "net" full package. Japanese version of this document is in "net" full package.
You can get it from RAA You can get it from RAA (Ruby Application Archive). RAA is:
(Ruby Application Archive: http://www.ruby-lang.org/en/raa.html). http://www.ruby-lang.org/en/raa.html
= class Net::HTTP == class Net::HTTP
== Class Methods === Class Methods
: 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.
@ -58,7 +60,7 @@
HTTP default port (80). HTTP default port (80).
== Instance Methods === Instance Methods
: start : start
: start {|http| .... } : start {|http| .... }
@ -119,12 +121,12 @@
If called with block, gives a HTTP response object to the block. If called with block, gives a HTTP response object to the block.
= class Net::HTTP::Get, Head, Post == class Net::HTTP::Get, Head, Post
HTTP request classes. These classes wraps request header and HTTP request classes. These classes wraps request header and
entity path. All "key" is case-insensitive. entity path. All "key" is case-insensitive.
== Methods === Methods
: self[ key ] : self[ key ]
returns header field for "key". returns header field for "key".
@ -133,53 +135,58 @@ entity path. All "key" is case-insensitive.
set header to "val". set header to "val".
= class Net::HTTPResponse == class Net::HTTPResponse
HTTP response class. This class wraps response header and entity. HTTP response class. This class wraps response header and entity.
All "key" is case-insensitive. All arguments named KEY is case-insensitive.
== Methods === Methods
: body
the entity body. ("dest" argument for HTTP#get, post, put)
: self[ key ] : self[ key ]
returns header field for "key". returns header field for KEY.
for HTTP, value is a string like 'text/plain'(for Content-Type), for HTTP, value is a string like 'text/plain' (for Content-Type),
'2045'(for Content-Length), 'bytes 0-1024/10024'(for Content-Range). '2045' (for Content-Length), 'bytes 0-1024/10024' (for Content-Range).
Multiple header had be joined by HTTP1.1 scheme. More than one fields which has same names are joined with ','.
KEY is case insensitive.
: self[ key ] = val : self[ key ] = val
set field value for "key". set field value for KEY.
KEY is inseisitive.
: key?( key ) : key?( key )
true if key exists true if key exists.
KEY is case insensitive.
: each {|name,value| .... } : each {|name,value| .... }
iterates for each field name and value pair iterates for each field name and value pair.
: canonical_each {|name,value| .... }
iterates for each canonical field name and value pair.
: code : code
HTTP result code string. For example, '302' HTTP result code string. For example, '302'.
: message : message
HTTP result message. For example, 'Not Found' HTTP result message. For example, 'Not Found'.
: read_body( dest = '' ) : read_body( dest = '' )
: body( dest = '' ) gets response body and write it into DEST using "<<" method.
gets response body. If this method is called twice or more, nothing will be done
It is written into "dest" using "<<" method. and returns first DEST.
If this method is called twice or more, nothing will be done and
returns first "dest".
: read_body {|str| .... } : read_body {|str| .... }
: body {|str| .... } gets response body little by little and pass it to block.
gets response body with 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.
= Swithing Net::HTTP versions == Swithing Net::HTTP versions
You can use Net::HTTP 1.1 features by calling HTTP.old_implementation. You can use Net::HTTP 1.1 features by calling HTTP.version_1_1 .
And calling Net::HTTP.new_implementation allows you to use 1.2 features And calling Net::HTTP.version_1_2 allows you to use 1.2 features
again. again.
# example # example
@ -206,9 +213,9 @@ module Net
HTTPVersion = '1.1' HTTPVersion = '1.1'
### #
### connection # connection
### #
protocol_param :port, '80' protocol_param :port, '80'
@ -223,6 +230,7 @@ module Net
@seems_1_0_server = false @seems_1_0_server = false
end end
private private
def conn_command( sock ) def conn_command( sock )
@ -232,9 +240,9 @@ module Net
end end
### #
### proxy # proxy
### #
public public
@ -417,9 +425,7 @@ module Net
def request( req, *args ) def request( req, *args )
common_oper( req ) { common_oper( req ) {
req.__send__( :exec, req.__send__( :exec,
@socket, @curr_http_version, @socket, @curr_http_version, edit_path(req.path), *args )
edit_path(req.path),
header_defaults, *args )
yield req.response if block_given? yield req.response if block_given?
} }
req.response req.response
@ -430,71 +436,59 @@ module Net
def common_oper( req ) def common_oper( req )
req['connection'] ||= 'keep-alive'
if not @socket then if not @socket then
start start
req['connection'] = 'close' req['connection'] = 'close'
elsif @socket.closed? then elsif @socket.closed? then
re_connect re_connect
end end
if @seems_1_0_server then if not req.body_exist? or @seems_1_0_server then
req['connection'] = 'close' req['connection'] = 'close'
end end
req['host'] = addr_port
yield req yield req
req.response.__send__ :terminate req.response.__send__ :terminate
@curr_http_version = req.response.http_version @curr_http_version = req.response.http_version
if keep_alive? req, req.response then if not req.response.body then
if @socket.closed? then @socket.close
elsif keep_alive? req, req.response then
D 'Conn keep-alive'
if @socket.closed? then # (only) read stream had been closed
D 'Conn (but seems 1.0 server)'
@seems_1_0_server = true @seems_1_0_server = true
@socket.close @socket.close
end end
else else
D 'Conn close'
@socket.close @socket.close
end end
req.response req.response
end end
def header_defaults def keep_alive?( req, res )
h = {} /close/i === req['connection'].to_s and return false
h['host'] = addr_port @seems_1_0_server and return false
h['connection'] = 'Keep-Alive'
h['accept'] = '*/*'
h
end
def keep_alive?( request, response ) /keep-alive/i === res['connection'].to_s and return true
if response.key? 'connection' then /close/i === res['connection'].to_s and return false
if /keep-alive/i === response['connection'] then /keep-alive/i === res['proxy-connection'].to_s and return true
return true /close/i === res['proxy-connection'].to_s and return false
end
elsif response.key? 'proxy-connection' then
if /keep-alive/i === response['proxy-connection'] then
return true
end
elsif request.key? 'Connection' then
if /keep-alive/i === request['Connection'] then
return true
end
else
if @curr_http_version == '1.1' then
return true
end
end
@curr_http_version == '1.1' and return true
false false
end end
def addr_port
address + (port == HTTP.port ? '' : ":#{port}")
end
# #
# utils # utils
# #
public
def self.get( addr, path, port = nil ) def self.get( addr, path, port = nil )
req = Get.new( path ) req = Get.new( path )
resp = nil resp = nil
@ -508,6 +502,20 @@ module Net
print get( addr, path, port ) print get( addr, path, port )
end end
private
def addr_port
address + (port == HTTP.port ? '' : ":#{port}")
end
def D( msg )
if @dout then
@dout << msg
@dout << "\n"
end
end
end end
HTTPSession = HTTP HTTPSession = HTTP
@ -580,7 +588,7 @@ module Net
### ###
### request ### header
### ###
net_private { net_private {
@ -657,7 +665,11 @@ module Net
return *arr return *arr
end end
def range=( r ) def range=( r, fin = nil )
if fin then
r = r ... r+fin
end
case r case r
when Numeric when Numeric
s = r > 0 ? "0-#{r - 1}" : "-#{-r}" s = r > 0 ? "0-#{r - 1}" : "-#{-r}"
@ -684,6 +696,8 @@ module Net
r r
end end
alias set_range range=
def content_length def content_length
s = @header['content-length'] s = @header['content-length']
s or return nil s or return nil
@ -695,7 +709,7 @@ module Net
def chunked? def chunked?
s = @header['transfer-encoding'] s = @header['transfer-encoding']
s and /(?:\A|[^\-\w])chunked(?:[^\-\w]|\z)/i === s (s and /(?:\A|[^\-\w])chunked(?:[^\-\w]|\z)/i === s) ? true : false
end end
def content_range def content_range
@ -713,8 +727,20 @@ module Net
r and r.length r and r.length
end end
def basic_auth( acc, pass )
@header['authorization'] = ["#{acc}:#{pass}"].pack('m').gsub(/\s+/, '')
end
end end
}
###
### request
###
net_private {
class HTTPRequest class HTTPRequest
@ -731,6 +757,7 @@ module Net
end end
tmp[ key ] = v.strip tmp[ key ] = v.strip
end end
tmp['accept'] ||= '*/*'
@socket = nil @socket = nil
@response = nil @response = nil
@ -743,6 +770,10 @@ module Net
"\#<#{type}>" "\#<#{type}>"
end end
def body_exist?
type::HAS_BODY
end
private private
@ -750,26 +781,25 @@ module Net
# write # write
# #
def exec( sock, ver, path, ihead ) def exec( sock, ver, path )
ready( sock, ihead ) {|header| ready( sock ) {
request ver, path, header request ver, path
} }
@response @response
end end
def ready( sock, ihead ) def ready( sock )
@response = nil @response = nil
@socket = sock @socket = sock
ihead.update @header yield
yield ihead
@response = get_response @response = get_response
@sock = nil @socket = nil
end end
def request( ver, path, header ) def request( ver, path )
@socket.writeline sprintf('%s %s HTTP/%s', type::METHOD, path, ver) @socket.writeline sprintf('%s %s HTTP/%s', type::METHOD, path, ver)
header.each do |n,v| canonical_each do |k,v|
@socket.writeline canonical(n) + ': ' + v @socket.writeline k + ': ' + v
end end
@socket.writeline '' @socket.writeline ''
end end
@ -822,11 +852,11 @@ module Net
end end
class HTTPRequestWithData < HTTPRequest class HTTPRequestWithBody < HTTPRequest
private private
def exec( sock, ver, path, ihead, str = nil ) def exec( sock, ver, path, str = nil )
check_arg str, block_given? check_arg str, block_given?
if block_given? then if block_given? then
@ -836,11 +866,11 @@ module Net
else else
data = str data = str
end end
@header['content-length'] = data.size.to_s
@header.delete 'transfer-encoding'
ready( sock, ihead ) {|header| ready( sock ) {
header['Content-Length'] = data.size.to_s request ver, path
header.delete 'Transfer-Encoding'
request ver, path, header
@socket.write data @socket.write data
} }
@response @response
@ -893,12 +923,12 @@ module Net
METHOD = 'HEAD' METHOD = 'HEAD'
end end
class Post < ::Net::NetPrivate::HTTPRequestWithData class Post < ::Net::NetPrivate::HTTPRequestWithBody
HAS_BODY = true HAS_BODY = true
METHOD = 'POST' METHOD = 'POST'
end end
class Put < ::Net::NetPrivate::HTTPRequestWithData class Put < ::Net::NetPrivate::HTTPRequestWithBody
HAS_BODY = true HAS_BODY = true
METHOD = 'PUT' METHOD = 'PUT'
end end
@ -990,9 +1020,7 @@ module Net
end end
def value def value
unless SuccessCode === self then SuccessCode === self or error! self
error! self
end
end end
@ -1080,9 +1108,7 @@ module Net
end end
def stream_check def stream_check
if @socket.closed? then @socket.closed? and raise IOError, 'try to read body out of block'
raise IOError, 'try to read body out of block'
end
end end
def procdest( dest, block ) def procdest( dest, block )

View File

@ -2,15 +2,17 @@
= net/pop.rb version 1.2.0 = net/pop.rb version 1.2.0
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> Copyright (C) 1999-2001 Yukihiro Matsumoto
This program is free software. written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
You can distribute/modify this program under
the terms of the Ruby Distribute License.
Japanese version of this document is in "net" full package. This program is free software. You can re-distribute and/or
You can get it from RAA modify this program under the same terms as Ruby itself,
(Ruby Application Archive: http://www.ruby-lang.org/en/raa.html). GNU General Public License or Ruby 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
== Net::POP3 == Net::POP3

View File

@ -2,15 +2,17 @@
= net/protocol.rb version 1.2.0 = net/protocol.rb version 1.2.0
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> Copyright (C) 1999-2001 Yukihiro Matsumoto
This program is free software. written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
You can distribute/modify this program under
the terms of the Ruby Distribute License.
Japanese version of this document is in "net" full package. This program is free software. You can re-distribute and/or
You can get it from RAA modify this program under the same terms as Ruby itself,
(Ruby Application Archive: http://www.ruby-lang.org/en/raa.html). GNU General Public License or Ruby 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
== Net::Protocol == Net::Protocol

View File

@ -2,15 +2,17 @@
= net/smtp.rb version 1.2.0 = net/smtp.rb version 1.2.0
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> Copyright (C) 1999-2001 Yukihiro Matsumoto
This program is free software. written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
You can distribute/modify this program under
the terms of the Ruby Distribute License.
Japanese version of this document is in "net" full package. This program is free software. You can re-distribute and/or
You can get it from RAA modify this program under the same terms as Ruby itself,
(Ruby Application Archive: http://www.ruby-lang.org/en/raa.html). GNU General Public License or Ruby 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
== Net::SMTP == Net::SMTP