Class: Net::HTTPResponse

Inherits:
Object
  • Object
show all
Includes:
HTTPHeader
Defined in:
lib/net/http/response.rb,
lib/net/http/responses.rb

Overview

This class is the base class for Net::HTTP response classes.

About the Examples

:include: doc/net-http/examples.rdoc

Returned Responses

Method Net::HTTP.get_response returns an instance of one of the subclasses of Net::HTTPResponse:

Net::HTTP.get_response(uri)
# => #<Net::HTTPOK 200 OK readbody=true>
Net::HTTP.get_response(hostname, '/nosuch')
# => #<Net::HTTPNotFound 404 Not Found readbody=true>

As does method Net::HTTP#request:

req = Net::HTTP::Get.new(uri)
Net::HTTP.start(hostname) do |http|
  http.request(req)
end # => #<Net::HTTPOK 200 OK readbody=true>

Class Net::HTTPResponse includes module Net::HTTPHeader, which provides access to response header values via (among others):

  • Hash-like method [].

  • Specific reader methods, such as content_type.

Examples:

res = Net::HTTP.get_response(uri) # => #<Net::HTTPOK 200 OK readbody=true>
res['Content-Type']               # => "text/html; charset=UTF-8"
res.content_type                  # => "text/html"

Response Subclasses

Class Net::HTTPResponse has a subclass for each HTTP status code. You can look up the response class for a given code:

Net::HTTPResponse::CODE_TO_OBJ['200'] # => Net::HTTPOK
Net::HTTPResponse::CODE_TO_OBJ['400'] # => Net::HTTPBadRequest
Net::HTTPResponse::CODE_TO_OBJ['404'] # => Net::HTTPNotFound

And you can retrieve the status code for a response object:

Net::HTTP.get_response(uri).code                 # => "200"
Net::HTTP.get_response(hostname, '/nosuch').code # => "404"

The response subclasses (indentation shows class hierarchy):

  • Net::HTTPUnknownResponse (for unhandled HTTP extensions).

  • Net::HTTPInformation:

    • Net::HTTPContinue (100)

    • Net::HTTPSwitchProtocol (101)

    • Net::HTTPProcessing (102)

    • Net::HTTPEarlyHints (103)

  • Net::HTTPSuccess:

    • Net::HTTPOK (200)

    • Net::HTTPCreated (201)

    • Net::HTTPAccepted (202)

    • Net::HTTPNonAuthoritativeInformation (203)

    • Net::HTTPNoContent (204)

    • Net::HTTPResetContent (205)

    • Net::HTTPPartialContent (206)

    • Net::HTTPMultiStatus (207)

    • Net::HTTPAlreadyReported (208)

    • Net::HTTPIMUsed (226)

  • Net::HTTPRedirection:

    • Net::HTTPMultipleChoices (300)

    • Net::HTTPMovedPermanently (301)

    • Net::HTTPFound (302)

    • Net::HTTPSeeOther (303)

    • Net::HTTPNotModified (304)

    • Net::HTTPUseProxy (305)

    • Net::HTTPTemporaryRedirect (307)

    • Net::HTTPPermanentRedirect (308)

  • Net::HTTPClientError:

    • Net::HTTPBadRequest (400)

    • Net::HTTPUnauthorized (401)

    • Net::HTTPPaymentRequired (402)

    • Net::HTTPForbidden (403)

    • Net::HTTPNotFound (404)

    • Net::HTTPMethodNotAllowed (405)

    • Net::HTTPNotAcceptable (406)

    • Net::HTTPProxyAuthenticationRequired (407)

    • Net::HTTPRequestTimeOut (408)

    • Net::HTTPConflict (409)

    • Net::HTTPGone (410)

    • Net::HTTPLengthRequired (411)

    • Net::HTTPPreconditionFailed (412)

    • Net::HTTPRequestEntityTooLarge (413)

    • Net::HTTPRequestURITooLong (414)

    • Net::HTTPUnsupportedMediaType (415)

    • Net::HTTPRequestedRangeNotSatisfiable (416)

    • Net::HTTPExpectationFailed (417)

    • Net::HTTPMisdirectedRequest (421)

    • Net::HTTPUnprocessableEntity (422)

    • Net::HTTPLocked (423)

    • Net::HTTPFailedDependency (424)

    • Net::HTTPUpgradeRequired (426)

    • Net::HTTPPreconditionRequired (428)

    • Net::HTTPTooManyRequests (429)

    • Net::HTTPRequestHeaderFieldsTooLarge (431)

    • Net::HTTPUnavailableForLegalReasons (451)

  • Net::HTTPServerError:

    • Net::HTTPInternalServerError (500)

    • Net::HTTPNotImplemented (501)

    • Net::HTTPBadGateway (502)

    • Net::HTTPServiceUnavailable (503)

    • Net::HTTPGatewayTimeOut (504)

    • Net::HTTPVersionNotSupported (505)

    • Net::HTTPVariantAlsoNegotiates (506)

    • Net::HTTPInsufficientStorage (507)

    • Net::HTTPLoopDetected (508)

    • Net::HTTPNotExtended (510)

    • Net::HTTPNetworkAuthenticationRequired (511)

There is also the Net::HTTPBadResponse exception which is raised when there is a protocol error.

Defined Under Namespace

Classes: Inflater

Constant Summary collapse

CODE_CLASS_TO_OBJ =

:stopdoc:

{
  '1' => Net::HTTPInformation,
  '2' => Net::HTTPSuccess,
  '3' => Net::HTTPRedirection,
  '4' => Net::HTTPClientError,
  '5' => Net::HTTPServerError
}.freeze
CODE_TO_OBJ =
{
  '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,
}.freeze

Constants included from HTTPHeader

Net::HTTPHeader::MAX_FIELD_LENGTH, Net::HTTPHeader::MAX_KEY_LENGTH

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HTTPHeader

#[], #[]=, #add_field, #basic_auth, #chunked?, #connection_close?, #connection_keep_alive?, #content_length, #content_length=, #content_range, #content_type, #delete, #each_capitalized, #each_capitalized_name, #each_header, #each_name, #each_value, #fetch, #get_fields, #initialize_http_header, #key?, #main_type, #proxy_basic_auth, #range, #range_length, #set_content_type, #set_form, #set_form_data, #set_range, #size, #sub_type, #to_hash, #type_params

Constructor Details

#initialize(httpv, code, msg) ⇒ HTTPResponse

:nodoc: internal use only



195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/net/http/response.rb', line 195

def initialize(httpv, code, msg)   #:nodoc: internal use only
  @http_version = httpv
  @code         = code
  @message      = msg
  initialize_http_header nil
  @body = nil
  @read = false
  @uri  = nil
  @decode_content = false
  @body_encoding = false
  @ignore_eof = true
end

Instance Attribute Details

#body_encodingObject

Returns the value set by body_encoding=, or false if none; see #body_encoding=.



230
231
232
# File 'lib/net/http/response.rb', line 230

def body_encoding
  @body_encoding
end

#codeObject (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.



214
215
216
# File 'lib/net/http/response.rb', line 214

def code
  @code
end

#decode_contentObject

Set to true automatically when the request did not contain an Accept-Encoding header from the user.



226
227
228
# File 'lib/net/http/response.rb', line 226

def decode_content
  @decode_content
end

#http_versionObject (readonly)

The HTTP version supported by the server.



209
210
211
# File 'lib/net/http/response.rb', line 209

def http_version
  @http_version
end

#ignore_eofObject

Whether to ignore EOF when reading bodies with a specified Content-Length header.



261
262
263
# File 'lib/net/http/response.rb', line 261

def ignore_eof
  @ignore_eof
end

#messageObject (readonly) Also known as: msg

The HTTP result message sent by the server. For example, ‘Not Found’.



217
218
219
# File 'lib/net/http/response.rb', line 217

def message
  @message
end

#uriObject

The URI used to fetch this response. The response URI is only available if a URI was used to create the request.



222
223
224
# File 'lib/net/http/response.rb', line 222

def uri
  @uri
end

Class Method Details

.body_permitted?Boolean

true if the response has a body.

Returns:

  • (Boolean)


138
139
140
# File 'lib/net/http/response.rb', line 138

def body_permitted?
  self::HAS_BODY
end

.exception_typeObject

:nodoc: internal use only



142
143
144
# File 'lib/net/http/response.rb', line 142

def exception_type   # :nodoc: internal use only
  self::EXCEPTION_TYPE
end

.read_new(sock) ⇒ Object

:nodoc: internal use only



146
147
148
149
150
151
152
153
# File 'lib/net/http/response.rb', line 146

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

Instance Method Details

#bodyObject Also known as: entity

Returns the string response body; note that repeated calls for the unmodified body return a cached string:

path = '/todos/1'
Net::HTTP.start(hostname) do |http|
  res = http.get(path)
  p res.body
  p http.head(path).body # No body.
end

Output:

"{\n  \"userId\": 1,\n  \"id\": 1,\n  \"title\": \"delectus aut autem\",\n  \"completed\": false\n}"
nil


401
402
403
# File 'lib/net/http/response.rb', line 401

def body
  read_body()
end

#body=(value) ⇒ Object

Sets the body of the response to the given value.



406
407
408
# File 'lib/net/http/response.rb', line 406

def body=(value)
  @body = value
end

#code_typeObject

response <-> exception relationship



271
272
273
# File 'lib/net/http/response.rb', line 271

def code_type   #:nodoc:
  self.class
end

#error!Object

:nodoc:

Raises:



275
276
277
278
279
# File 'lib/net/http/response.rb', line 275

def error!   #:nodoc:
  message = @code
  message = "#{message} #{@message.dump}" if @message
  raise error_type().new(message, self)
end

#error_typeObject

:nodoc:



281
282
283
# File 'lib/net/http/response.rb', line 281

def error_type   #:nodoc:
  self.class::EXCEPTION_TYPE
end

#headerObject

:nodoc:



303
304
305
306
# File 'lib/net/http/response.rb', line 303

def header   #:nodoc:
  warn "Net::HTTPResponse#header is obsolete", uplevel: 1 if $VERBOSE
  self
end

#inspectObject

:nodoc:



263
264
265
# File 'lib/net/http/response.rb', line 263

def inspect   # :nodoc:
  "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
end

#read_body(dest = nil, &block) ⇒ Object

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
}


356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'lib/net/http/response.rb', line 356

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
  return if @body.nil?

  case enc = @body_encoding
  when Encoding, false, nil
    # Encoding: force given encoding
    # false/nil: do not force encoding
  else
    # other value: detect encoding from body
    enc = detect_encoding(@body)
  end

  @body.force_encoding(enc) if enc

  @body
end

#read_headerObject

:nodoc:



308
309
310
311
# File 'lib/net/http/response.rb', line 308

def read_header   #:nodoc:
  warn "Net::HTTPResponse#read_header is obsolete", uplevel: 1 if $VERBOSE
  self
end

#reading_body(sock, reqmethodallowbody) ⇒ Object

body



317
318
319
320
321
322
323
324
325
326
# File 'lib/net/http/response.rb', line 317

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

#responseObject

header (for backward compatibility only; DO NOT USE)



298
299
300
301
# File 'lib/net/http/response.rb', line 298

def response   #:nodoc:
  warn "Net::HTTPResponse#response is obsolete", uplevel: 1 if $VERBOSE
  self
end

#valueObject

Raises an HTTP error if the response is not 2xx (success).



286
287
288
# File 'lib/net/http/response.rb', line 286

def value
  error! unless self.kind_of?(Net::HTTPSuccess)
end