Class: LunaPark::Http::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/luna_park/http/response.rb

Overview

Http response value object.

Constant Summary collapse

STATUSES =

List of descriptions http codes

{
  # Informational response
  100 => 'Continue',
  101 => 'Switching Protocols',
  102 => 'Processing',                   # RFC '251'8 (WebDAV)
  103 => 'Early Hints',                  # RFC 8297

  # Success
  200 => 'OK',
  201 => 'Created',
  202 => 'Accepted',
  203 => 'Non-Authoritative Information',
  204 => 'No Content',
  205 => 'Reset Content',
  206 => 'Partial Content',
  207 => 'Multi-Status',                 # RFC '251'8 (WebDAV)
  208 => 'Already Reported',             # RFC '584'2
  226 => 'IM Used',                      # RFC 3229

  # Redirection
  300 => 'Multiple Choices',
  301 => 'Moved Permanently',
  302 => 'Found',
  303 => 'See Other',
  304 => 'Not Modified',
  305 => 'Use Proxy',
  307 => 'Temporary Redirect',
  308 => 'Permanent Redirect', # RFC 7538

  # Client error
  400 => 'Bad Request',
  401 => 'Unauthorized',
  402 => 'Payment Required',
  403 => 'Forbidden',
  404 => 'Not Found',
  405 => 'Method Not Allowed',
  406 => 'Not Acceptable',
  407 => 'Proxy Authentication Required',
  408 => 'Request Timeout',
  409 => 'Conflict',
  410 => 'Gone',
  411 => 'Length Required',
  412 => 'Precondition Failed',
  413 => 'Request Entity Too Large',
  414 => 'Request-URI Too Large',
  415 => 'Unsupported Media Type',
  416 => 'Request Range Not Satisfiable',
  417 => 'Expectation Failed',
  418 => 'I\'m a teapot',            # RFC '232'4;          RFC 7168 section 2.3.3
  422 => 'Unprocessable Entity',     # RFC '251'8 (WebDAV); RFC 4918 section 11.2
  423 => 'Locked',                   # RFC '251'8 (WebDAV)
  424 => 'Failed Dependency',        # RFC '251'8 (WebDAV)
  425 => 'No code',                  # WebDAV Advanced Collections
  426 => 'Upgrade Required',         # RFC '281'7
  428 => 'Precondition Required',
  429 => 'Too Many Requests',
  431 => 'Request Header Fields Too Large',
  449 => 'Retry with',                     # unofficial Microsoft
  451 => 'Unavailable For Legal Reasons',  # RFC 7725
  452 => 'Unavailable For Legal Reasons',  # ! Not confirmed: RFC 7225 The code 451 was chosen as a reference to the novel Fahrenheit 451
  # Server errors
  500 => 'Internal Server Error',
  501 => 'Not Implemented',
  502 => 'Bad Gateway',
  503 => 'Service Unavailable',
  504 => 'Gateway Timeout',
  505 => 'HTTP Version Not Supported',
  506 => 'Variant Also Negotiates',         # RFC '229'5
  507 => 'Insufficient Storage',            # RFC '251'8 (WebDAV)
  509 => 'Bandwidth Limit Exceeded',        # unofficial
  510 => 'Not Extended',                    # RFC '277'4
  511 => 'Network Authentication Required'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request:, code:, body: '', headers: {}, cookies: {}) ⇒ Response

Create new response

Parameters:

  • request (LunaPark::Http::Request)
  • code (Integer)
  • body (String) (defaults to: '')
  • headers (Hash) (defaults to: {})
  • cookies (Hash) (defaults to: {})


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

def initialize(request:, code:, body: '', headers: {}, cookies: {})
  @request = request
  @code    = Integer(code)
  @body    = String(body)
  @headers = Hash(headers)
  @cookies = Hash(cookies)
end

Instance Attribute Details

#bodyObject (readonly)

Response body

Examples:

json response

response.body # => "{\"message\":\"pong\"}"

Returns:

  • String



90
91
92
# File 'lib/luna_park/http/response.rb', line 90

def body
  @body
end

#codeObject (readonly)

Http code, reference: rfc7231

Examples:

success response

response.code # => 200

Returns:

  • Integer



98
99
100
# File 'lib/luna_park/http/response.rb', line 98

def code
  @code
end

#cookiesObject (readonly)

Hash of cookies

Examples:

secret keys

response.cookies # => {'secret' => '6f7a8459e4330122cac2b9752506a813610b814d'}

Returns:

  • Hash



114
115
116
# File 'lib/luna_park/http/response.rb', line 114

def cookies
  @cookies
end

#exceptionObject

Exception of failed request Can be raised after call (without bang) Will be raised after call! (with bang)

Returns:

  • LunaPark::Errors::Http



121
122
123
# File 'lib/luna_park/http/response.rb', line 121

def exception
  @exception
end

#headersObject (readonly)

Headers of http response

Examples:

json response

response.headers # => { 'Content-Type': 'application/json' }

Returns:

  • Hash



106
107
108
# File 'lib/luna_park/http/response.rb', line 106

def headers
  @headers
end

#requestObject (readonly)

The request that actually initializes the current response

Examples:

request = Request.new(
  title: 'Get users list',
  method: :get,
  url: 'http://example.com/users'
)
response = request.call
response.request === request # => true
response.request # => "<LunaPark::Http::Request @title=\"Get users\"
                 #       @url=\"http://localhost:8080/get_200\" @method=\"get\"
                 #       @headers=\"{}\" @body=\"\" @sent_at=\"\">"

Returns:

  • LunaPark::Http::Response



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

def request
  @request
end

Instance Method Details

#==(other) ⇒ Object

Two response should be equal, if their attributes (request, code, body, headers, cookies) match.



380
381
382
383
384
385
386
387
# File 'lib/luna_park/http/response.rb', line 380

def ==(other)
  return false unless other.is_a? Response

  code      == other.code    &&
    body    == other.body    &&
    headers == other.headers &&
    cookies == other.cookies
end

#client_error?Boolean

Check this response code is 4xx

Examples:

response status - ‘Unprocessable Entity`

response.code          # => 422
response.client_error? # => true

response status - ‘Success`

response.code          # => 200
response.client_error? # => false

Returns:

  • (Boolean)


234
235
236
# File 'lib/luna_park/http/response.rb', line 234

def client_error?
  (400..499).cover?(code)
end

#informational_response?Boolean

Check this response code is 1xx

Examples:

response status - ‘Continue`

response.code                    # => 100
response.informational_response? # => true

response status - ‘Success`

response.code                    # => 200
response.informational_response? # => false

Returns:

  • (Boolean)


188
189
190
# File 'lib/luna_park/http/response.rb', line 188

def informational_response?
  (100..199).cover?(code)
end

#inspectString

Examples:

inspect get users index request

request = LunaPark::Http::Request.new(
  title: 'Get users',
  method: :get,
  url: 'http://localhost:8080/get_200'
)

response = LunaPark::Http::Request.new(
  code: 200,
  body: "{\"users\":[{\"name\":\"john\"}]",
  headers: {'Content-Type': 'application/json'}
)

request.inspect # => "<LunaPark::Http::Request @title=\"Get users\"
                #  @url=\"http://localhost:8080/get_200\" @method=\"get\"
                #  @headers=\"{}\" @body=\"\" @sent_at=\"\">"

Returns:

  • (String)


173
174
175
# File 'lib/luna_park/http/response.rb', line 173

def inspect
  "<#{self.class.name} @code=#{code} @body=\"#{body}\" @headers=#{headers} @cookies=#{cookies}>"
end

#json_parse(payload_key: nil, stringify_keys: false) ⇒ Hash, ...

Try to parse this response body from JSON format. If body doesn`t consists expected JSON format, you get nil. Also you can get only payload data if define payload_key.

Examples:

parse from json whole data

response.body # => "{\"version\": 1, \"data\":{\"message\":\"pong\"}}"
response.json_parse! # => {version: 1, data: { message: 'pong' }}

get only payload data

response.body # => "{\"version\": 1, \"data\":{\"message\":\"pong\"}}"
response.json_parse! payload_key: :data # => { message: 'pong' }

parse from json whole data with string keys

response.body # => "{\"version\": 1, \"data\":{\"message\":\"pong\"}}"
response.json_parse! stringify_keys: true # => {'version' => 1, 'data' => { 'message' => 'pong' }}

get data from non-json body data

response.body # => "pong"
response.json_parse! # => nil

Parameters:

  • payload_key (String, Symbol) (defaults to: nil)
    • key of payload data

  • stringify_keys (Boolean) (defaults to: false)
    • output hash should

Returns:

  • (Hash, String, nil)


347
348
349
350
351
# File 'lib/luna_park/http/response.rb', line 347

def json_parse(payload_key: nil, stringify_keys: false)
  json_parse!(payload_key: payload_key, stringify_keys: stringify_keys)
rescue Errors::JsonParse
  nil
end

#json_parse!(payload_key: nil, stringify_keys: false) ⇒ Hash, String

Try to parse this response body from JSON format. If body doesn`t consists expected JSON format, you catch Errors::JsonParse. Also you can get only payload data if define payload_key.

Examples:

parse from json whole data

response.body # => "{\"version\": 1, \"data\":{\"message\":\"pong\"}}"
response.json_parse! # => {version: 1, data: { message: 'pong' }}

get only payload data

response.body # => "{\"version\": 1, \"data\":{\"message\":\"pong\"}}"
response.json_parse! payload_key: :data # => { message: 'pong' }

parse from json whole data with string keys

response.body # => "{\"version\": 1, \"data\":{\"message\":\"pong\"}}"
response.json_parse! stringify_keys: true # => {'version' => 1, 'data' => { 'message' => 'pong' }}

get data from non-json body data

response.body # => "pong"
response.json_parse! # => raise Errors::JsonParse

Parameters:

  • payload_key (String, Symbol) (defaults to: nil)
    • key of payload data

  • stringify_keys (Boolean) (defaults to: false)
    • output hash should

Returns:

  • (Hash, String)


313
314
315
316
317
318
319
320
321
# File 'lib/luna_park/http/response.rb', line 313

def json_parse!(payload_key: nil, stringify_keys: false)
  data = JSON.parse(body, symbolize_names: !stringify_keys)
  return data unless payload_key

  payload_key = stringify_keys ? payload_key.to_s : payload_key.to_sym
  data.fetch(payload_key)
rescue KeyError, JSON::ParserError => e
  raise Errors::JsonParse.substitute(e)
end

#redirection?Boolean

Check this response code is 3xx

Examples:

response status - ‘Permanent Redirect`

response.code         # => 308
response.redirection? # => true

response status - ‘Success`

response.code         # => 200
response.redirection? # => false

Returns:

  • (Boolean)


219
220
221
# File 'lib/luna_park/http/response.rb', line 219

def redirection?
  (300..399).cover?(code)
end

#server_error?Boolean

Check this response code is 5xx

Examples:

response status - ‘Internal Server Error`

response.code          # => 500
response.server_error? # => true

response status - ‘Success`

response.code          # => 200
response.server_error? # => false

Returns:

  • (Boolean)


249
250
251
# File 'lib/luna_park/http/response.rb', line 249

def server_error?
  (500..599).cover?(code)
end

#statusObject

Describes what the code means in a human-readable format.

Examples:

when the object is successfully created

response.code # => 201
response.code # => 'Created'

when the server is down

response.code # => 503
response.code # => 'Service Unavailable'


285
286
287
# File 'lib/luna_park/http/response.rb', line 285

def status
  STATUSES[code] || 'Unknown'
end

#success?Boolean

Returns:

  • (Boolean)


204
205
206
# File 'lib/luna_park/http/response.rb', line 204

def success?
  (200..299).cover?(code)
end

#to_hHash

Examples:

response.to_h # => {
  :code=>200,
  :body=>"John Doe, Marry Ann",
  :headers=>{}, :cookies=>{},
  :request=>{
    :title=>"Get users",
    :method=>:get,
    :url=>"http://localhost:8080/get_200",
    :body=>nil,
    :headers=>{},
    :read_timeout=>10,
    :open_timeout=>10, :sent_at=>nil
  }
}

Returns:

  • (Hash)


369
370
371
372
373
374
375
376
377
# File 'lib/luna_park/http/response.rb', line 369

def to_h
  {
    code: code,
    body: body,
    headers: headers,
    cookies: cookies,
    request: request.to_h
  }
end

#typeSymbol

Return response code type. It can be

  • :informational_response - for response with 1xx code

  • :success - for response with 2xx code

  • :redirection - for response with 3xx code

  • :client_error - for response with 4xx code

  • :server_error - for response with 5xx code

Examples:

success response

response.code # => 200
response.type # => :success

Returns:

  • (Symbol)


265
266
267
268
269
270
271
272
273
274
# File 'lib/luna_park/http/response.rb', line 265

def type
  case code
  when 100..199 then :informational_response
  when 200..299 then :success
  when 300..399 then :redirection
  when 400..499 then :client_error
  when 500..599 then :server_error
  else :unknown
  end
end