Class: PatientHttp::Response

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

Overview

Represents an HTTP response from an async request.

This class encapsulates the response data including status, headers, body, and metadata about the request that generated it.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(status:, headers:, body:, duration:, request_id:, url:, http_method:, callback_args: nil, redirects: nil) ⇒ Response

Initialize a Response from an Async::HTTP::Response

Parameters:

  • status (Integer)

    HTTP status code

  • headers (Hash, HttpHeaders)

    response headers

  • body (String, nil)

    response body

  • duration (Float)

    request duration in seconds

  • request_id (String)

    the request ID

  • url (String)

    the request URL

  • http_method (Symbol)

    the HTTP method

  • callback_args (Hash, nil) (defaults to: nil)

    callback arguments (string keys)

  • redirects (Array<String>, nil) (defaults to: nil)

    URLs visited during redirect chain



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/patient_http/response.rb', line 67

def initialize(status:, headers:, body:, duration:, request_id:, url:, http_method:, callback_args: nil, redirects: nil)
  @status = status
  @headers = HttpHeaders.new(headers)

  encoding, encoded_body, charset = Payload.encode(body, @headers["content-type"])
  @payload = Payload.new(encoding, encoded_body, charset) unless body.nil?
  @body = UNDEFINED

  @duration = duration
  @request_id = request_id
  @url = url
  @http_method = http_method
  @callback_args_data = callback_args || {}
  @redirects = redirects || []
end

Instance Attribute Details

#durationFloat (readonly)

Returns request duration in seconds.

Returns:

  • (Float)

    request duration in seconds



22
23
24
# File 'lib/patient_http/response.rb', line 22

def duration
  @duration
end

#headersHttpHeaders (readonly)

Response headers. Headers that appeared multiple times in the response (such as set-cookie) are flattened into a single joined string value.

Returns:



19
20
21
# File 'lib/patient_http/response.rb', line 19

def headers
  @headers
end

#http_methodSymbol (readonly)

Returns HTTP method.

Returns:

  • (Symbol)

    HTTP method



31
32
33
# File 'lib/patient_http/response.rb', line 31

def http_method
  @http_method
end

#redirectsArray<String> (readonly)

Returns URLs visited during redirect chain (empty if no redirects).

Returns:

  • (Array<String>)

    URLs visited during redirect chain (empty if no redirects)



34
35
36
# File 'lib/patient_http/response.rb', line 34

def redirects
  @redirects
end

#request_idString (readonly)

Returns request ID.

Returns:

  • (String)

    request ID



25
26
27
# File 'lib/patient_http/response.rb', line 25

def request_id
  @request_id
end

#statusInteger (readonly)

Returns HTTP status code.

Returns:

  • (Integer)

    HTTP status code



13
14
15
# File 'lib/patient_http/response.rb', line 13

def status
  @status
end

#urlString (readonly)

Returns request URL.

Returns:

  • (String)

    request URL



28
29
30
# File 'lib/patient_http/response.rb', line 28

def url
  @url
end

Class Method Details

.load(hash) ⇒ Response

Reconstruct a Response from a hash

Parameters:

  • hash (Hash)

    hash representation

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/patient_http/response.rb', line 41

def load(hash)
  new(
    status: hash["status"],
    headers: hash["headers"],
    body: Payload.load(hash["body"])&.value,
    duration: hash["duration"],
    request_id: hash["request_id"],
    url: hash["url"],
    http_method: hash["http_method"]&.to_sym,
    callback_args: hash["callback_args"],
    redirects: hash["redirects"]
  )
end

Instance Method Details

#as_jsonHash

Serialize to JSON hash.

Returns:

  • (Hash)


164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/patient_http/response.rb', line 164

def as_json
  {
    "status" => status,
    "headers" => headers.to_h,
    "body" => @payload&.as_json,
    "duration" => duration,
    "request_id" => request_id,
    "url" => url,
    "http_method" => http_method.to_s,
    "callback_args" => @callback_args_data,
    "redirects" => @redirects
  }
end

#bodyString?

Returns the response body, decoding it from the payload if necessary.

Returns:

  • (String, nil)

    The decoded response body or nil if there was no body.



93
94
95
96
# File 'lib/patient_http/response.rb', line 93

def body
  @body = @payload&.value if @body.equal?(UNDEFINED)
  @body
end

#callback_argsCallbackArgs

Returns the callback arguments as a CallbackArgs object.

Returns:



86
87
88
# File 'lib/patient_http/response.rb', line 86

def callback_args
  @callback_args ||= CallbackArgs.load(@callback_args_data)
end

#client_error?Boolean

Check if response is a client error (4xx status)

Returns:

  • (Boolean)


115
116
117
# File 'lib/patient_http/response.rb', line 115

def client_error?
  status >= 400 && status < 500
end

#content_typeString?

Get the Content-Type header

Returns:

  • (String, nil)


136
137
138
# File 'lib/patient_http/response.rb', line 136

def content_type
  headers["content-type"]
end

#error?Boolean

Check if response is any error (4xx or 5xx status)

Returns:

  • (Boolean)


129
130
131
# File 'lib/patient_http/response.rb', line 129

def error?
  status >= 400 && status < 600
end

#jsonHash, Array

Parse response body as JSON

Returns:

  • (Hash, Array)

    parsed JSON

Raises:

  • (RuntimeError)

    if Content-Type is not application/json

  • (JSON::ParserError)

    if body is not valid JSON



153
154
155
156
157
158
159
# File 'lib/patient_http/response.rb', line 153

def json
  unless json?
    raise "Response Content-Type is not application/json (got: #{content_type.inspect})"
  end

  JSON.parse(body)
end

#json?Boolean

Return true if Content-Type indicates JSON.

Returns:

  • (Boolean)


143
144
145
146
# File 'lib/patient_http/response.rb', line 143

def json?
  type = content_type.to_s.downcase
  type.match?(%r{\Aapplication/[^ ]*json\b}) || type == "text/json"
end

#redirect?Boolean

Check if response is a redirect (3xx status)

Returns:

  • (Boolean)


108
109
110
# File 'lib/patient_http/response.rb', line 108

def redirect?
  status >= 300 && status < 400
end

#server_error?Boolean

Check if response is a server error (5xx status)

Returns:

  • (Boolean)


122
123
124
# File 'lib/patient_http/response.rb', line 122

def server_error?
  status >= 500 && status < 600
end

#success?Boolean

Check if response is successful (2xx status)

Returns:

  • (Boolean)


101
102
103
# File 'lib/patient_http/response.rb', line 101

def success?
  status >= 200 && status < 300
end

#to_json(options = nil) ⇒ String

Serialize to JSON string.

Parameters:

  • options (Hash) (defaults to: nil)

    options to pass to JSON.generate (for ActiveSupport compatibility)

Returns:

  • (String)

    JSON representation



182
183
184
# File 'lib/patient_http/response.rb', line 182

def to_json(options = nil)
  JSON.generate(as_json, options)
end