ruby-changes:23710
From: drbrain <ko1@a...>
Date: Wed, 23 May 2012 05:36:34 +0900 (JST)
Subject: [ruby-changes:23710] drbrain:r35761 (trunk): * lib/net/http.rb: Broke up Net::HTTP into individual files.
drbrain 2012-05-23 05:36:21 +0900 (Wed, 23 May 2012) New Revision: 35761 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35761 Log: * lib/net/http.rb: Broke up Net::HTTP into individual files. [ruby-trunk - Feature #6435] * lib/net/http/backward.rb: ditto. * lib/net/http/response.rb: ditto. * lib/net/http/exceptions.rb: ditto. * lib/net/http/responses.rb: ditto. * lib/net/http/generic_request.rb: ditto. * lib/net/http/header.rb: ditto. * lib/net/http/request.rb: ditto. * lib/net/http/proxy_delta.rb: ditto. * lib/net/http/requests.rb: ditto. Added directories: trunk/lib/net/http/ Added files: trunk/lib/net/http/backward.rb trunk/lib/net/http/exceptions.rb trunk/lib/net/http/generic_request.rb trunk/lib/net/http/header.rb trunk/lib/net/http/proxy_delta.rb trunk/lib/net/http/request.rb trunk/lib/net/http/requests.rb trunk/lib/net/http/response.rb trunk/lib/net/http/responses.rb Modified files: trunk/ChangeLog trunk/lib/net/http.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 35760) +++ ChangeLog (revision 35761) @@ -1,3 +1,17 @@ +Wed May 23 05:35:58 2012 Eric Hodel <drbrain@s...> + + * lib/net/http.rb: Broke up Net::HTTP into individual files. + [ruby-trunk - Feature #6435] + * lib/net/http/backward.rb: ditto. + * lib/net/http/response.rb: ditto. + * lib/net/http/exceptions.rb: ditto. + * lib/net/http/responses.rb: ditto. + * lib/net/http/generic_request.rb: ditto. + * lib/net/http/header.rb: ditto. + * lib/net/http/request.rb: ditto. + * lib/net/http/proxy_delta.rb: ditto. + * lib/net/http/requests.rb: ditto. + Wed May 23 05:15:11 2012 Eric Hodel <drbrain@s...> * class.c (rb_mod_init_copy): Clear the cached inspect string of a Index: lib/net/http/backward.rb =================================================================== --- lib/net/http/backward.rb (revision 0) +++ lib/net/http/backward.rb (revision 35761) @@ -0,0 +1,22 @@ +# for backward compatibility + +# :enddoc: + +class Net::HTTP + ProxyMod = ProxyDelta + HTTPSession = self +end + +module Net::NetPrivate + HTTPRequest = ::Net::HTTPRequest +end + +Net::HTTPInformationCode = Net::HTTPInformation +Net::HTTPSuccessCode = Net::HTTPSuccess +Net::HTTPRedirectionCode = Net::HTTPRedirection +Net::HTTPRetriableCode = Net::HTTPRedirection +Net::HTTPClientErrorCode = Net::HTTPClientError +Net::HTTPFatalErrorCode = Net::HTTPClientError +Net::HTTPServerErrorCode = Net::HTTPServerError +Net::HTTPResponceReceiver = Net::HTTPResponse + Property changes on: lib/net/http/backward.rb ___________________________________________________________________ Added: svn:eol-style + LF Index: lib/net/http/response.rb =================================================================== --- lib/net/http/response.rb (revision 0) +++ lib/net/http/response.rb (revision 35761) @@ -0,0 +1,332 @@ +# HTTP response class. +# +# This class wraps together the response header and the response body (the +# entity requested). +# +# It mixes in the HTTPHeader module, which provides access to response +# header values both via hash-like methods and via individual readers. +# +# Note that each possible HTTP response code defines its own +# HTTPResponse subclass. These are listed below. +# +# All classes are +# defined under the Net module. Indentation indicates inheritance. +# +# xxx HTTPResponse +# +# 1xx HTTPInformation +# 100 HTTPContinue +# 101 HTTPSwitchProtocol +# +# 2xx HTTPSuccess +# 200 HTTPOK +# 201 HTTPCreated +# 202 HTTPAccepted +# 203 HTTPNonAuthoritativeInformation +# 204 HTTPNoContent +# 205 HTTPResetContent +# 206 HTTPPartialContent +# +# 3xx HTTPRedirection +# 300 HTTPMultipleChoice +# 301 HTTPMovedPermanently +# 302 HTTPFound +# 303 HTTPSeeOther +# 304 HTTPNotModified +# 305 HTTPUseProxy +# 307 HTTPTemporaryRedirect +# +# 4xx HTTPClientError +# 400 HTTPBadRequest +# 401 HTTPUnauthorized +# 402 HTTPPaymentRequired +# 403 HTTPForbidden +# 404 HTTPNotFound +# 405 HTTPMethodNotAllowed +# 406 HTTPNotAcceptable +# 407 HTTPProxyAuthenticationRequired +# 408 HTTPRequestTimeOut +# 409 HTTPConflict +# 410 HTTPGone +# 411 HTTPLengthRequired +# 412 HTTPPreconditionFailed +# 413 HTTPRequestEntityTooLarge +# 414 HTTPRequestURITooLong +# 415 HTTPUnsupportedMediaType +# 416 HTTPRequestedRangeNotSatisfiable +# 417 HTTPExpectationFailed +# +# 5xx HTTPServerError +# 500 HTTPInternalServerError +# 501 HTTPNotImplemented +# 502 HTTPBadGateway +# 503 HTTPServiceUnavailable +# 504 HTTPGatewayTimeOut +# 505 HTTPVersionNotSupported +# +# xxx HTTPUnknownResponse +# +class Net::HTTPResponse + class << self + # true if the response has a body. + def body_permitted? + self::HAS_BODY + end + + def exception_type # :nodoc: internal use only + self::EXCEPTION_TYPE + end + + def read_new(sock) #:nodoc: internal use only + httpv, code, msg = read_status_line(sock) + res = response_class(code).new(httpv, code, msg) + each_response_header(sock) do |k,v| + res.add_field k, v + end + res + end + + private + + def read_status_line(sock) + str = sock.readline + m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str) or + raise Net::HTTPBadResponse, "wrong status line: #{str.dump}" + m.captures + end + + def response_class(code) + CODE_TO_OBJ[code] or + CODE_CLASS_TO_OBJ[code[0,1]] or + Net::HTTPUnknownResponse + end + + def each_response_header(sock) + key = value = nil + while true + line = sock.readuntil("\n", true).sub(/\s+\z/, '') + break if line.empty? + if line[0] == ?\s or line[0] == ?\t and value + value << ' ' unless value.empty? + value << line.strip + else + yield key, value if key + key, value = line.strip.split(/\s*:\s*/, 2) + raise Net::HTTPBadResponse, 'wrong header line format' if value.nil? + end + end + yield key, value if key + end + end + + # next is to fix bug in RDoc, where the private inside class << self + # spills out. + public + + include Net::HTTPHeader + + def initialize(httpv, code, msg) #:nodoc: internal use only + @http_version = httpv + @code = code + @message = msg + initialize_http_header nil + @body = nil + @read = false + end + + # The HTTP version supported by the server. + attr_reader :http_version + + # The HTTP result code string. For example, '302'. You can also + # determine the response type by examining which response subclass + # the response object is an instance of. + attr_reader :code + + # The HTTP result message sent by the server. For example, 'Not Found'. + attr_reader :message + alias msg message # :nodoc: obsolete + + def inspect + "#<#{self.class} #{@code} #{@message} readbody=#{@read}>" + end + + # + # response <-> exception relationship + # + + def code_type #:nodoc: + self.class + end + + def error! #:nodoc: + raise error_type().new(@code + ' ' + @message.dump, self) + end + + def error_type #:nodoc: + self.class::EXCEPTION_TYPE + end + + # Raises an HTTP error if the response is not 2xx (success). + def value + error! unless self.kind_of?(Net::HTTPSuccess) + end + + # + # header (for backward compatibility only; DO NOT USE) + # + + def response #:nodoc: + warn "#{caller(1)[0]}: warning: Net::HTTPResponse#response is obsolete" if $VERBOSE + self + end + + def header #:nodoc: + warn "#{caller(1)[0]}: warning: Net::HTTPResponse#header is obsolete" if $VERBOSE + self + end + + def read_header #:nodoc: + warn "#{caller(1)[0]}: warning: Net::HTTPResponse#read_header is obsolete" if $VERBOSE + self + end + + # + # body + # + + def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only + @socket = sock + @body_exist = reqmethodallowbody && self.class.body_permitted? + begin + yield + self.body # ensure to read body + ensure + @socket = nil + end + end + + # Gets the entity body returned by the remote HTTP server. + # + # If a block is given, the body is passed to the block, and + # the body is provided in fragments, as it is read in from the socket. + # + # Calling this method a second or subsequent time for the same + # HTTPResponse object will return the value already read. + # + # http.request_get('/index.html') {|res| + # puts res.read_body + # } + # + # http.request_get('/index.html') {|res| + # p res.read_body.object_id # 538149362 + # p res.read_body.object_id # 538149362 + # } + # + # # using iterator + # http.request_get('/index.html') {|res| + # res.read_body do |segment| + # print segment + # end + # } + # + def read_body(dest = nil, &block) + if @read + raise IOError, "#{self.class}\#read_body called twice" if dest or block + return @body + end + to = procdest(dest, block) + stream_check + if @body_exist + read_body_0 to + @body = to + else + @body = nil + end + @read = true + + @body + end + + # Returns the full entity body. + # + # Calling this method a second or subsequent time will return the + # string already read. + # + # http.request_get('/index.html') {|res| + # puts res.body + # } + # + # http.request_get('/index.html') {|res| + # p res.body.object_id # 538149362 + # p res.body.object_id # 538149362 + # } + # + def body + read_body() + end + + # Because it may be necessary to modify the body, Eg, decompression + # this method facilitates that. + def body=(value) + @body = value + end + + alias entity body #:nodoc: obsolete + + private + + def read_body_0(dest) + if chunked? + read_chunked dest + return + end + clen = content_length() + if clen + @socket.read clen, dest, true # ignore EOF + return + end + clen = range_length() + if clen + @socket.read clen, dest + return + end + @socket.read_all dest + end + + def read_chunked(dest) + len = nil + total = 0 + while true + line = @socket.readline + hexlen = line.slice(/[0-9a-fA-F]+/) or + raise Net::HTTPBadResponse, "wrong chunk size line: #{line}" + len = hexlen.hex + break if len == 0 + begin + @socket.read len, dest + ensure + total += len + @socket.read 2 # \r\n + end + end + until @socket.readline.empty? + # none + end + end + + def stream_check + raise IOError, 'attempt to read body out of block' if @socket.closed? + end + + def procdest(dest, block) + raise ArgumentError, 'both arg and block given for HTTP method' \ + if dest and block + if block + Net::ReadAdapter.new(block) + else + dest || '' + end + end + +end + Property changes on: lib/net/http/response.rb ___________________________________________________________________ Added: svn:eol-style + LF Index: lib/net/http/exceptions.rb =================================================================== --- lib/net/http/exceptions.rb (revision 0) +++ lib/net/http/exceptions.rb (revision 35761) @@ -0,0 +1,25 @@ +# Net::HTTP exception class. +# You cannot use Net::HTTPExceptions directly; instead, you must use +# its subclasses. +module Net::HTTPExceptions + def initialize(msg, res) #:nodoc: + super msg + @response = res + end + attr_reader :response + alias data response #:nodoc: obsolete +end +class Net::HTTPError < Net::ProtocolError + include Net::HTTPExceptions +end +class Net::HTTPRetriableError < Net::ProtoRetriableError + include Net::HTTPExceptions +end +class Net::HTTPServerException < Net::ProtoServerError + # We cannot use the name "HTTPServerError", it is the name of the response. + include Net::HTTPExceptions +end +class Net::HTTPFatalError < Net::ProtoFatalError + include Net::HTTPExceptions +end + Property changes on: lib/net/http/exceptions.rb ___________________________________________________________________ Added: svn:eol-style + LF Index: lib/net/http/responses.rb =================================================================== --- lib/net/http/responses.rb (revision 0) +++ lib/net/http/responses.rb (revision 35761) @@ -0,0 +1,212 @@ +# :stopdoc: +class Net::HTTPUnknownResponse < Net::HTTPResponse + HAS_BODY = true + EXCEPTION_TYPE = Net::HTTPError +end +class Net::HTTPInformation < Net::HTTPResponse # 1xx + HAS_BODY = false + EXCEPTION_TYPE = Net::HTTPError +end +class Net::HTTPSuccess < Net::HTTPResponse # 2xx + HAS_BODY = true + EXCEPTION_TYPE = Net::HTTPError +end +class Net::HTTPRedirection < Net::HTTPResponse # 3xx + HAS_BODY = true + EXCEPTION_TYPE = Net::HTTPRetriableError +end +class Net::HTTPClientError < Net::HTTPResponse # 4xx + HAS_BODY = true + EXCEPTION_TYPE = Net::HTTPServerException # for backward compatibility +end +class Net::HTTPServerError < Net::HTTPResponse # 5xx + HAS_BODY = true + EXCEPTION_TYPE = Net::HTTPFatalError # for backward compatibility +end + +class Net::HTTPContinue < Net::HTTPInformation # 100 + HAS_BODY = false +end +class Net::HTTPSwitchProtocol < Net::HTTPInformation # 101 + HAS_BODY = false +end + +class Net::HTTPOK < Net::HTTPSuccess # 200 + HAS_BODY = true +end +class Net::HTTPCreated < Net::HTTPSuccess # 201 + HAS_BODY = true +end +class Net::HTTPAccepted < Net::HTTPSuccess # 202 + HAS_BODY = true +end +class Net::HTTPNonAuthoritativeInformation < Net::HTTPSuccess # 203 + HAS_BODY = true +end +class Net::HTTPNoContent < Net::HTTPSuccess # 204 + HAS_BODY = false +end +class Net::HTTPResetContent < Net::HTTPSuccess # 205 + HAS_BODY = false +end +class Net::HTTPPartialContent < Net::HTTPSuccess # 206 + HAS_BODY = true +end + +class Net::HTTPMultipleChoice < Net::HTTPRedirection # 300 + HAS_BODY = true +end +class Net::HTTPMovedPermanently < Net::HTTPRedirection # 301 + HAS_BODY = true +end +class Net::HTTPFound < Net::HTTPRedirection # 302 + HAS_BODY = true +end +Net::HTTPMovedTemporarily = Net::HTTPFound +class Net::HTTPSeeOther < Net::HTTPRedirection # 303 + HAS_BODY = true +end +class Net::HTTPNotModified < Net::HTTPRedirection # 304 + HAS_BODY = false +end +class Net::HTTPUseProxy < Net::HTTPRedirection # 305 + HAS_BODY = false +end +# 306 unused +class Net::HTTPTemporaryRedirect < Net::HTTPRedirection # 307 + HAS_BODY = true +end + +class Net::HTTPBadRequest < Net::HTTPClientError # 400 + HAS_BODY = true +end +class Net::HTTPUnauthorized < Net::HTTPClientError # 401 + HAS_BODY = true +end +class Net::HTTPPaymentRequired < Net::HTTPClientError # 402 + HAS_BODY = true +end +class Net::HTTPForbidden < Net::HTTPClientError # 403 + HAS_BODY = true +end +class Net::HTTPNotFound < Net::HTTPClientError # 404 + HAS_BODY = true +end +class Net::HTTPMethodNotAllowed < Net::HTTPClientError # 405 + HAS_BODY = true +end +class Net::HTTPNotAcceptable < Net::HTTPClientError # 406 + HAS_BODY = true +end +class Net::HTTPProxyAuthenticationRequired < Net::HTTPClientError # 407 + HAS_BODY = true +end +class Net::HTTPRequestTimeOut < Net::HTTPClientError # 408 + HAS_BODY = true +end +class Net::HTTPConflict < Net::HTTPClientError # 409 + HAS_BODY = true +end +class Net::HTTPGone < Net::HTTPClientError # 410 + HAS_BODY = true +end +class Net::HTTPLengthRequired < Net::HTTPClientError # 411 + HAS_BODY = true +end +class Net::HTTPPreconditionFailed < Net::HTTPClientError # 412 + HAS_BODY = true +end +class Net::HTTPRequestEntityTooLarge < Net::HTTPClientError # 413 + HAS_BODY = true +end +class Net::HTTPRequestURITooLong < Net::HTTPClientError # 414 + HAS_BODY = true +end +Net::HTTPRequestURITooLarge = Net::HTTPRequestURITooLong +class Net::HTTPUnsupportedMediaType < Net::HTTPClientError # 415 + HAS_BODY = true +end +class Net::HTTPRequestedRangeNotSatisfiable < Net::HTTPClientError # 416 + HAS_BODY = true +end +class Net::HTTPExpectationFailed < Net::HTTPClientError # 417 + HAS_BODY = true +end + +class Net::HTTPInternalServerError < Net::HTTPServerError # 500 + HAS_BODY = true +end +class Net::HTTPNotImplemented < Net::HTTPServerError # 501 + HAS_BODY = true +end +class Net::HTTPBadGateway < Net::HTTPServerError # 502 + HAS_BODY = true +end +class Net::HTTPServiceUnavailable < Net::HTTPServerError # 503 + HAS_BODY = true +end +class Net::HTTPGatewayTimeOut < Net::HTTPServerError # 504 + HAS_BODY = true +end +class Net::HTTPVersionNotSupported < Net::HTTPServerError # 505 + HAS_BODY = true +end + +class Net::HTTPResponse + CODE_CLASS_TO_OBJ = { + '1' => Net::HTTPInformation, + '2' => Net::HTTPSuccess, + '3' => Net::HTTPRedirection, + '4' => Net::HTTPClientError, + '5' => Net::HTTPServerError + } + CODE_TO_OBJ = { + '100' => Net::HTTPContinue, + '101' => Net::HTTPSwitchProtocol, + + '200' => Net::HTTPOK, + '201' => Net::HTTPCreated, + '202' => Net::HTTPAccepted, + '203' => Net::HTTPNonAuthoritativeInformation, + '204' => Net::HTTPNoContent, + '205' => Net::HTTPResetContent, + '206' => Net::HTTPPartialContent, + + '300' => Net::HTTPMultipleChoice, + '301' => Net::HTTPMovedPermanently, + '302' => Net::HTTPFound, + '303' => Net::HTTPSeeOther, + '304' => Net::HTTPNotModified, + '305' => Net::HTTPUseProxy, + '307' => Net::HTTPTemporaryRedirect, + + '400' => Net::HTTPBadRequest, + '401' => Net::HTTPUnauthorized, + '402' => Net::HTTPPaymentRequired, + '403' => Net::HTTPForbidden, + '404' => Net::HTTPNotFound, + '405' => Net::HTTPMethodNotAllowed, + '406' => Net::HTTPNotAcceptable, + '407' => Net::HTTPProxyAuthenticationRequired, + '408' => Net::HTTPRequestTimeOut, + '409' => Net::HTTPConflict, + '410' => Net::HTTPGone, + '411' => Net::HTTPLengthRequired, + '412' => Net::HTTPPreconditionFailed, + '413' => Net::HTTPRequestEntityTooLarge, + '414' => Net::HTTPRequestURITooLong, + '415' => Net::HTTPUnsupportedMediaType, + '416' => Net::HTTPRequestedRangeNotSatisfiable, + '417' => Net::HTTPExpectationFailed, + + '500' => Net::HTTPInternalServerError, + '501' => Net::HTTPNotImplemented, + '502' => Net::HTTPBadGateway, + '503' => Net::HTTPServiceUnavailable, + '504' => Net::HTTPGatewayTimeOut, + '505' => Net::HTTPVersionNotSupported + } +end + +# :startdoc: + Property changes on: lib/net/http/responses.rb ___________________________________________________________________ Added: svn:eol-style + LF Index: lib/net/http/generic_request.rb =================================================================== --- lib/net/http/generic_request.rb (revision 0) +++ lib/net/http/generic_request.rb (revision 35761) @@ -0,0 +1,254 @@ +# HTTPGenericRequest is the parent of the HTTPRequest class. +# Do not use this directly; use a subclass of HTTPRequest. +# +# Mixes in the HTTPHeader module to provide easier access to HTTP headers. +# +class Net::HTTPGenericRequest + + include Net::HTTPHeader + + def initialize(m, reqbody, resbody, path, initheader = nil) + @method = m + @request_has_body = reqbody + @response_has_body = resbody + raise ArgumentError, "no HTTP request path given" unless path + raise ArgumentError, "HTTP request path is empty" if path.empty? + @path = path + initialize_http_header initheader + self['Accept'] ||= '*/*' + self['User-Agent'] ||= 'Ruby' + @body = nil + @body_stream = nil + @body_data = nil + end + + attr_reader :method + attr_reader :path + + def inspect + "\#<#{self.class} #{@method}>" + end + + def request_body_permitted? + @request_has_body + end + + def response_body_permitted? + @response_has_body + end + + def body_exist? + warn "Net::HTTPRequest#body_exist? is obsolete (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/