Class: Net::HTTPResponse
Overview
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. All classes are defined under the ::Net
module. Indentation indicates inheritance. For a list of the classes see HTTP
.
Correspondence HTTP code => class
is stored in CODE_TO_OBJ constant:
Net::HTTPResponse::CODE_TO_OBJ['404'] #=> Net::HTTPNotFound
Constant Summary
-
CODE_CLASS_TO_OBJ =
Internal use only
# File 'lib/net/http/responses.rb', line 232{ '1' => Net::HTTPInformation, '2' => Net::HTTPSuccess, '3' => Net::HTTPRedirection, '4' => Net::HTTPClientError, '5' => Net::HTTPServerError }
-
CODE_TO_OBJ =
Internal use only
# File 'lib/net/http/responses.rb', line 239{ '100' => Net::HTTPContinue, '101' => Net::HTTPSwitchProtocol, '102' => Net::HTTPProcessing, '103' => Net::HTTPEarlyHints, '200' => Net::HTTPOK, '201' => Net::HTTPCreated, '202' => Net::HTTPAccepted, '203' => Net::HTTPNonAuthoritativeInformation, '204' => Net::HTTPNoContent, '205' => Net::HTTPResetContent, '206' => Net::HTTPPartialContent, '207' => Net::HTTPMultiStatus, '208' => Net::HTTPAlreadyReported, '226' => Net::HTTPIMUsed, '300' => Net::HTTPMultipleChoices, '301' => Net::HTTPMovedPermanently, '302' => Net::HTTPFound, '303' => Net::HTTPSeeOther, '304' => Net::HTTPNotModified, '305' => Net::HTTPUseProxy, '307' => Net::HTTPTemporaryRedirect, '308' => Net::HTTPPermanentRedirect, '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::HTTPPayloadTooLarge, '414' => Net::HTTPURITooLong, '415' => Net::HTTPUnsupportedMediaType, '416' => Net::HTTPRangeNotSatisfiable, '417' => Net::HTTPExpectationFailed, '421' => Net::HTTPMisdirectedRequest, '422' => Net::HTTPUnprocessableEntity, '423' => Net::HTTPLocked, '424' => Net::HTTPFailedDependency, '426' => Net::HTTPUpgradeRequired, '428' => Net::HTTPPreconditionRequired, '429' => Net::HTTPTooManyRequests, '431' => Net::HTTPRequestHeaderFieldsTooLarge, '451' => Net::HTTPUnavailableForLegalReasons, '500' => Net::HTTPInternalServerError, '501' => Net::HTTPNotImplemented, '502' => Net::HTTPBadGateway, '503' => Net::HTTPServiceUnavailable, '504' => Net::HTTPGatewayTimeout, '505' => Net::HTTPVersionNotSupported, '506' => Net::HTTPVariantAlsoNegotiates, '507' => Net::HTTPInsufficientStorage, '508' => Net::HTTPLoopDetected, '510' => Net::HTTPNotExtended, '511' => Net::HTTPNetworkAuthenticationRequired, }
HTTPHeader
- Included
Class Attribute Summary
-
.body_permitted? ⇒ Boolean
readonly
true if the response has a body.
Class Method Summary
- .each_response_header(sock) {|key, value| ... } private
- .read_status_line(sock) private
- .response_class(code) private
-
.exception_type
Internal use only
internal use only.
-
.new(httpv, code, msg) ⇒ HTTPResponse
constructor
Internal use only
internal use only.
-
.read_new(sock)
Internal use only
internal use only.
Instance Attribute Summary
-
#body
(also: #entity)
rw
Returns the full entity body.
-
#body=(value)
rw
Because it may be necessary to modify the body, Eg, decompression this method facilitates that.
-
#code
readonly
The HTTP result code string.
-
#decode_content
rw
Set to true automatically when the request did not contain an Accept-Encoding header from the user.
-
#http_version
readonly
The HTTP version supported by the server.
-
#message
(also: #msg)
readonly
The HTTP result message sent by the server.
-
#uri
rw
The URI used to fetch this response.
-
#entity
readonly
Internal use only
Alias for #body.
-
#msg
readonly
Internal use only
Alias for #message.
- #uri=(uri) rw Internal use only
HTTPHeader
- Included
#chunked? | Returns “true” if the “transfer-encoding” header is present and set to “chunked”. |
#connection_close?, #connection_keep_alive?, | |
#content_length | Returns an Integer object which represents the |
#content_length= |
Instance Method Summary
- #inspect
-
#read_body(dest = nil, &block)
Gets the entity body returned by the remote
HTTP
server. -
#value
Raises an
HTTP
error if the response is not 2xx (success). - #procdest(dest, block) private
- #read_body_0(dest) private
- #stream_check private
-
#code_type
Internal use only
response <-> exception relationship.
- #error! Internal use only
- #error_type Internal use only
- #header Internal use only
- #read_header Internal use only
-
#reading_body(sock, reqmethodallowbody)
Internal use only
body.
-
#response
Internal use only
header (for backward compatibility only; DO NOT USE).
-
#inflater
private
Internal use only
Checks for a supported Content-Encoding header and yields an Inflate wrapper for this response’s socket when zlib is present.
-
#read_chunked(dest, chunk_data_io)
private
Internal use only
read_chunked reads from @socket for chunk-size, chunk-extension, CRLF, etc.
HTTPHeader
- Included
#[] | Returns the header field corresponding to the case-insensitive key. |
#[]= | Sets the header field corresponding to the case-insensitive key. |
#add_field |
|
#basic_auth | Set the Authorization: header for “Basic” authorization. |
#canonical_each | Alias for HTTPHeader#each_capitalized. |
#content_range | Returns a Range object which represents the value of the Content-Range: header field. |
#content_type | Returns a content type string such as “text/html”. |
#content_type= | Alias for HTTPHeader#set_content_type. |
#delete | Removes a header field, specified by case-insensitive key. |
#each | Alias for HTTPHeader#each_header. |
#each_capitalized | As for |
#each_capitalized_name | Iterates through the header names in the header, passing capitalized header names to the code block. |
#each_header | Iterates through the header names and values, passing in the name and value to the code block supplied. |
#each_key | Alias for HTTPHeader#each_name. |
#each_name | Iterates through the header names in the header, passing each header name to the code block. |
#each_value | Iterates through header values, passing each value to the code block. |
#fetch | Returns the header field corresponding to the case-insensitive key. |
#form_data= | Alias for HTTPHeader#set_form_data. |
#get_fields |
|
#initialize_http_header, | |
#key? | true if |
#main_type | Returns a content type string such as “text”. |
#proxy_basic_auth | Set Proxy-Authorization: header for “Basic” authorization. |
#range | Returns an Array of Range objects which represent the Range: |
#range= | Alias for HTTPHeader#set_range. |
#range_length | The length of the range represented in Content-Range: header. |
#set_content_type | Sets the content type in an |
#set_form | Set an HTML form data set. |
#set_form_data | Set header fields and a body from HTML form data. |
#set_range | Sets the |
#sub_type | Returns a content type string such as “html”. |
#to_hash | Returns a Hash consisting of header names and array of values. |
#type_params | Any parameters specified for the content type, returned as a Hash. |
#append_field_value, #basic_encode, #capitalize, #set_field, | |
#length | Alias for HTTPHeader#size. |
#size | obsolete. |
Constructor Details
.new(httpv, code, msg) ⇒ HTTPResponse
internal use only
Class Attribute Details
.body_permitted? ⇒ Boolean
(readonly)
true if the response has a body.
# File 'lib/net/http/response.rb', line 22
def body_permitted? self::HAS_BODY end
Class Method Details
.each_response_header(sock) {|key, value| ... } (private)
# File 'lib/net/http/response.rb', line 54
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
.exception_type
internal use only
# File 'lib/net/http/response.rb', line 26
def exception_type # :nodoc: internal use only self::EXCEPTION_TYPE end
.read_new(sock)
internal use only
# File 'lib/net/http/response.rb', line 30
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
.read_status_line(sock) (private)
[ GitHub ]# File 'lib/net/http/response.rb', line 41
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
.response_class(code) (private)
[ GitHub ]# File 'lib/net/http/response.rb', line 48
def response_class(code) CODE_TO_OBJ[code] or CODE_CLASS_TO_OBJ[code[0,1]] or Net::HTTPUnknownResponse end
Instance Attribute Details
#body (rw) Also known as: #entity
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
}
# File 'lib/net/http/response.rb', line 234
def body read_body() end
#body=(value) (rw)
Because it may be necessary to modify the body, Eg, decompression this method facilitates that.
#code (readonly)
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.
# File 'lib/net/http/response.rb', line 95
attr_reader :code
#decode_content (rw)
Set to true automatically when the request did not contain an Accept-Encoding header from the user.
# File 'lib/net/http/response.rb', line 107
attr_accessor :decode_content
#entity (readonly)
Alias for #body.
# File 'lib/net/http/response.rb', line 244
alias entity body #:nodoc: obsolete
#http_version (readonly)
The HTTP version supported by the server.
# File 'lib/net/http/response.rb', line 90
attr_reader :http_version
#message (readonly) Also known as: #msg
The HTTP result message sent by the server. For example, ‘Not Found’.
# File 'lib/net/http/response.rb', line 98
attr_reader :
#msg (readonly)
Alias for #message.
# File 'lib/net/http/response.rb', line 99
alias msg # :nodoc: obsolete
#uri (rw)
The URI used to fetch this response. The response URI is only available if a URI was used to create the request.
# File 'lib/net/http/response.rb', line 103
attr_reader :uri
#uri=(uri) (rw)
Instance Method Details
#code_type
response <-> exception relationship
# File 'lib/net/http/response.rb', line 117
def code_type #:nodoc: self.class end
#error!
# File 'lib/net/http/response.rb', line 121
def error! #:nodoc: = @code += ' ' + @message.dump if @message raise error_type().new(, self) end
#error_type
# File 'lib/net/http/response.rb', line 127
def error_type #:nodoc: self.class::EXCEPTION_TYPE end
#header
# File 'lib/net/http/response.rb', line 149
def header #:nodoc: warn "Net::HTTPResponse#header is obsolete", uplevel: 1 if $VERBOSE self end
#inflater (private)
Checks for a supported Content-Encoding header and yields an Inflate wrapper for this response’s socket when zlib is present. If the Content-Encoding is not supported or zlib is missing, the plain socket is yielded.
If a Content-Range header is present, a plain socket is yielded as the bytes in the range may not be a complete deflate block.
# File 'lib/net/http/response.rb', line 257
def inflater # :nodoc: return yield @socket unless Net::HTTP::HAVE_ZLIB return yield @socket unless @decode_content return yield @socket if self['content-range'] v = self['content-encoding'] case v&.downcase when 'deflate', 'gzip', 'x-gzip' then self.delete 'content-encoding' inflate_body_io = Inflater.new(@socket) begin yield inflate_body_io success = true ensure begin inflate_body_io.finish rescue => err # Ignore #finish's error if there is an exception from yield raise err if success end end when 'none', 'identity' then self.delete 'content-encoding' yield @socket else yield @socket end end
#inspect
[ GitHub ]# File 'lib/net/http/response.rb', line 109
def inspect "#<#{self.class} #{@code} #{@message} readbody=#{@read}>" end
#procdest(dest, block) (private)
#read_body(dest = nil, &block)
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.
If dest
argument is given, response is read into that variable, with dest#<<
method (it could be String or IO, or any other object responding to <<
).
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
}
# File 'lib/net/http/response.rb', line 202
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
#read_body_0(dest) (private)
[ GitHub ]# File 'lib/net/http/response.rb', line 289
def read_body_0(dest) inflater do |inflate_body_io| if chunked? read_chunked dest, inflate_body_io return end @socket = inflate_body_io 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 end
#read_chunked(dest, chunk_data_io) (private)
read_chunked reads from @socket for chunk-size, chunk-extension, CRLF, etc. and chunk_data_io
for chunk-data which may be deflate or gzip encoded.
See RFC 2616 section 3.6.1 for definitions
# File 'lib/net/http/response.rb', line 319
def read_chunked(dest, chunk_data_io) # :nodoc: 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 chunk_data_io.read len, dest ensure total += len @socket.read 2 # \r\n end end until @socket.readline.empty? # none end end
#read_header
# File 'lib/net/http/response.rb', line 154
def read_header #:nodoc: warn "Net::HTTPResponse#read_header is obsolete", uplevel: 1 if $VERBOSE self end
#reading_body(sock, reqmethodallowbody)
body
# File 'lib/net/http/response.rb', line 163
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
#response
header (for backward compatibility only; DO NOT USE)
# File 'lib/net/http/response.rb', line 144
def response #:nodoc: warn "Net::HTTPResponse#response is obsolete", uplevel: 1 if $VERBOSE self end
#stream_check (private)
# File 'lib/net/http/response.rb', line 339
def stream_check raise IOError, 'attempt to read body out of block' if @socket.closed? end
#value
Raises an HTTP
error if the response is not 2xx (success).
# File 'lib/net/http/response.rb', line 132
def value error! unless self.kind_of?(Net::HTTPSuccess) end