summaryrefslogtreecommitdiff
path: root/lib/net/http.rb
diff options
context:
space:
mode:
authoraamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-07-03 18:13:13 +0000
committeraamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-07-03 18:13:13 +0000
commitfa20d931bcd07a5f7d8ab80edc79419cae1d25fd (patch)
tree473e6f99e4c32093e56ce94107a33f6f0b0a9760 /lib/net/http.rb
parentfc1f22d5a8c0ba8dc04bfda6a14d910de1e04333 (diff)
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
Diffstat (limited to 'lib/net/http.rb')
-rw-r--r--lib/net/http.rb252
1 files changed, 142 insertions, 110 deletions
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]] ||