class HTTPX::Request

  1. lib/httpx/request.rb
  2. lib/httpx/request/body.rb
  3. show all
Superclass: Object

Defines how an HTTP request is handled internally, both in terms of making attributes accessible, as well as maintaining the state machine which manages streaming the request onto the wire.

Included modules

  1. Loggable
  2. Callbacks

Classes and Modules

  1. HTTPX::Request::Body

Constants

ALLOWED_URI_SCHEMES = %w[https http].freeze  

Attributes

active_timeouts [R]
body [R]

an HTTPX::Request::Body object containing the request body payload (or nil, whenn there is none).

connection [W]

the connection the request is currently being sent to (none if before or after transaction)

drain_error [R]

Exception raised during enumerable body writes.

headers [R]

an HTTPX::Headers object containing the request HTTP headers.

options [R]

an HTTPX::Options object containing request options.

peer_address [RW]

The IP address from the peer server.

persistent [W]
response [R]

the corresponding HTTPX::Response object, when there is one.

state [R]

a symbol describing which frame is currently being flushed.

uri [R]

the absolute URI object for this request.

verb [R]

the upcased string HTTP verb for this request.

Public Class methods

new(verb, uri, options, params = EMPTY_HASH)

initializes the instance with the given verb (an upppercase String, ex. ‘GEt’), an absolute or relative uri (either as String or URI::HTTP object), the request options (instance of HTTPX::Options) and an optional Hash of params.

Besides any of the options documented in HTTPX::Options (which would override or merge with what options sets), it accepts also the following:

:params

hash or array of key-values which will be encoded and set in the query string of request uris.

:body

to be encoded in the request body payload. can be a String, an IO object (i.e. a File), or an Enumerable.

:form

hash of array of key-values which will be form-urlencoded- or multipart-encoded in requests body payload.

:json

hash of array of key-values which will be JSON-encoded in requests body payload.

:xml

Nokogiri XML nodes which will be encoded in requests body payload.

:body, :form, :json and :xml are all mutually exclusive, i.e. only one of them gets picked up.

[show source]
    # File lib/httpx/request.rb
 72 def initialize(verb, uri, options, params = EMPTY_HASH)
 73   @verb    = verb.to_s.upcase
 74   @uri     = Utils.to_uri(uri)
 75 
 76   @headers = options.headers.dup
 77   merge_headers(params.delete(:headers)) if params.key?(:headers)
 78 
 79   @query_params = params.delete(:params) if params.key?(:params)
 80 
 81   @body = options.request_body_class.new(@headers, options, **params)
 82 
 83   @options = @body.options
 84 
 85   if @uri.relative? || @uri.host.nil?
 86     origin = @options.origin
 87     raise(Error, "invalid URI: #{@uri}") unless origin
 88 
 89     base_path = @options.base_path
 90 
 91     @uri = origin.merge("#{base_path}#{@uri}")
 92   end
 93 
 94   raise UnsupportedSchemeError, "#{@uri}: #{@uri.scheme}: unsupported URI scheme" unless ALLOWED_URI_SCHEMES.include?(@uri.scheme)
 95 
 96   @state = :idle
 97   @connection = @response = @drainer = @peer_address = @informational_status = nil
 98   @ping = false
 99   @persistent = @options.persistent
100   @active_timeouts = []
101 end

Public Instance methods

authority()

returs the URI authority of the request.

session.build_request("GET", "https://google.com/query").authority #=> "google.com"
session.build_request("GET", "http://internal:3182/a").authority #=> "internal:3182"
[show source]
    # File lib/httpx/request.rb
219 def authority
220   @uri.authority
221 end
can_buffer?()
[show source]
    # File lib/httpx/request.rb
161 def can_buffer?
162   @state != :done
163 end
complete!(response = @response)
[show source]
    # File lib/httpx/request.rb
111 def complete!(response = @response)
112   emit(:complete, response)
113 end
drain_body()

consumes and returns the next available chunk of request body that can be sent

[show source]
    # File lib/httpx/request.rb
249 def drain_body
250   return nil if @body.nil?
251 
252   @drainer ||= @body.each
253   chunk = @drainer.next.dup
254 
255   emit(:body_chunk, chunk)
256   chunk
257 rescue StopIteration
258   nil
259 rescue StandardError => e
260   @drain_error = e
261   nil
262 end
expects?()

whether the request supports the 100-continue handshake and already processed the 100 response.

[show source]
    # File lib/httpx/request.rb
314 def expects?
315   @headers["expect"] == "100-continue" && @informational_status == 100 && !@response
316 end
handle_error(error)
[show source]
    # File lib/httpx/request.rb
327 def handle_error(error)
328   if (connection = @connection)
329     connection.on_error(error, self)
330   else
331     response = ErrorResponse.new(self, error)
332     self.response = response
333     emit(:response, response)
334   end
335 end
initialize_dup(orig)

dupped initialization

[show source]
    # File lib/httpx/request.rb
104 def initialize_dup(orig)
105   super
106   @uri = orig.instance_variable_get(:@uri).dup
107   @headers = orig.instance_variable_get(:@headers).dup
108   @body = orig.instance_variable_get(:@body).dup
109 end
inspect()

:nocov:

[show source]
    # File lib/httpx/request.rb
265 def inspect
266   "#<#{self.class}:#{object_id} " \
267     "#{@verb} " \
268     "#{uri} " \
269     "@headers=#{@headers} " \
270     "@body=#{@body}>"
271 end
interests()

returns :r or :w, depending on whether the request is waiting for a response or flushing.

[show source]
    # File lib/httpx/request.rb
155 def interests
156   return :r if @state == :done || @state == :expect
157 
158   :w
159 end
merge_headers(h)

merges h into the instance of HTTPX::Headers of the request.

[show source]
    # File lib/httpx/request.rb
166 def merge_headers(h)
167   @headers = @headers.merge(h)
168   return unless @headers.key?("range")
169 
170   @headers.delete("accept-encoding")
171 end
origin()

returs the URI origin of the request.

session.build_request("GET", "https://google.com/query").authority #=> "https://google.com"
session.build_request("GET", "http://internal:3182/a").authority #=> "http://internal:3182"
[show source]
    # File lib/httpx/request.rb
227 def origin
228   @uri.origin
229 end
path()

returnns the URI path of the request uri.

[show source]
    # File lib/httpx/request.rb
207 def path
208   path = uri.path.dup
209   path =  +"" if path.nil?
210   path << "/" if path.empty?
211   path << "?#{query}" unless query.empty?
212   path
213 end
persistent?()
[show source]
    # File lib/httpx/request.rb
140 def persistent?
141   @persistent
142 end
ping!()

marks the request as having been buffered with a ping

[show source]
    # File lib/httpx/request.rb
121 def ping!
122   @ping = true
123 end
ping?()

whether request has been buffered with a ping

[show source]
    # File lib/httpx/request.rb
116 def ping?
117   @ping
118 end
query()

returs the URI query string of the request (when available).

session.build_request("GET", "https://search.com").query #=> ""
session.build_request("GET", "https://search.com?q=a").query #=> "q=a"
session.build_request("GET", "https://search.com", params: { q: "a"}).query #=> "q=a"
session.build_request("GET", "https://search.com?q=a", params: { foo: "bar"}).query #=> "q=a&foo&bar"
[show source]
    # File lib/httpx/request.rb
237 def query
238   return @query if defined?(@query)
239 
240   query = []
241   if (q = @query_params) && !q.empty?
242     query << Transcoder::Form.encode(q)
243   end
244   query << @uri.query if @uri.query
245   @query = query.join("&")
246 end
read_timeout()

the read timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
126 def read_timeout
127   @options.timeout[:read_timeout]
128 end
request_timeout()

the request timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
136 def request_timeout
137   @options.timeout[:request_timeout]
138 end
response=(response)

sets the response on this request.

[show source]
    # File lib/httpx/request.rb
179 def response=(response)
180   return unless response
181 
182   case response
183   when Response
184     if response.status < 200
185       # deal with informational responses
186 
187       if response.status == 100 && @headers.key?("expect")
188         @informational_status = response.status
189         return
190       end
191 
192       # 103 Early Hints advertises resources in document to browsers.
193       # not very relevant for an HTTP client, discard.
194       return if response.status >= 103
195 
196     end
197   when ErrorResponse
198     response.error.connection = nil if response.error.respond_to?(:connection=)
199   end
200 
201   @response = response
202 
203   emit(:response_started, response)
204 end
scheme()

the URI scheme of the request uri.

[show source]
    # File lib/httpx/request.rb
174 def scheme
175   @uri.scheme
176 end
set_timeout_callback(event, &callback)
[show source]
    # File lib/httpx/request.rb
318 def set_timeout_callback(event, &callback)
319   clb = once(event, &callback)
320 
321   # reset timeout callbacks when requests get rerouted to a different connection
322   once(:idle) do
323     callbacks(event).delete(clb)
324   end
325 end
trailers()

returns an instance of HTTPX::Headers containing the trailer headers

[show source]
    # File lib/httpx/request.rb
150 def trailers
151   @trailers ||= @options.headers_class.new
152 end
trailers?()

if the request contains trailer headers

[show source]
    # File lib/httpx/request.rb
145 def trailers?
146   defined?(@trailers)
147 end
transition(nextstate)

moves on to the nextstate of the request state machine (when all preconditions are met)

[show source]
    # File lib/httpx/request.rb
275 def transition(nextstate)
276   case nextstate
277   when :idle
278     @body.rewind
279     @ping = false
280     @response = @drainer = nil
281     @active_timeouts.clear
282   when :headers
283     return unless @state == :idle
284 
285   when :body
286     return unless @state == :headers ||
287                   @state == :expect
288 
289     if @headers.key?("expect")
290       if @informational_status && @informational_status == 100
291         # check for 100 Continue response, and deallocate the var
292         # if @informational_status == 100
293         #   @response = nil
294         # end
295       else
296         return if @state == :expect # do not re-set it
297 
298         nextstate = :expect
299       end
300     end
301   when :trailers
302     return unless @state == :body
303   when :done
304     return if @state == :expect
305 
306   end
307   log(level: 3) { "#{@state}] -> #{nextstate}" }
308   @state = nextstate
309   emit(@state, self)
310   nil
311 end
write_timeout()

the write timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
131 def write_timeout
132   @options.timeout[:write_timeout]
133 end