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).

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
69 def initialize(verb, uri, options, params = EMPTY_HASH)
70   @verb    = verb.to_s.upcase
71   @uri     = Utils.to_uri(uri)
72 
73   @headers = options.headers.dup
74   merge_headers(params.delete(:headers)) if params.key?(:headers)
75 
76   @query_params = params.delete(:params) if params.key?(:params)
77 
78   @body = options.request_body_class.new(@headers, options, **params)
79 
80   @options = @body.options
81 
82   if @uri.relative? || @uri.host.nil?
83     origin = @options.origin
84     raise(Error, "invalid URI: #{@uri}") unless origin
85 
86     base_path = @options.base_path
87 
88     @uri = origin.merge("#{base_path}#{@uri}")
89   end
90 
91   raise UnsupportedSchemeError, "#{@uri}: #{@uri.scheme}: unsupported URI scheme" unless ALLOWED_URI_SCHEMES.include?(@uri.scheme)
92 
93   @state = :idle
94   @response = @peer_address = @informational_status = nil
95   @ping = false
96   @persistent = @options.persistent
97   @active_timeouts = []
98 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
216 def authority
217   @uri.authority
218 end
can_buffer?()
[show source]
    # File lib/httpx/request.rb
158 def can_buffer?
159   @state != :done
160 end
complete!(response = @response)
[show source]
    # File lib/httpx/request.rb
108 def complete!(response = @response)
109   emit(:complete, response)
110 end
drain_body()

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

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

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

[show source]
    # File lib/httpx/request.rb
312 def expects?
313   @headers["expect"] == "100-continue" && @informational_status == 100 && !@response
314 end
initialize_dup(orig)

dupped initialization

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

:nocov:

[show source]
    # File lib/httpx/request.rb
262 def inspect
263   "#<#{self.class}:#{object_id} " \
264     "#{@verb} " \
265     "#{uri} " \
266     "@headers=#{@headers} " \
267     "@body=#{@body}>"
268 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
152 def interests
153   return :r if @state == :done || @state == :expect
154 
155   :w
156 end
merge_headers(h)

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

[show source]
    # File lib/httpx/request.rb
163 def merge_headers(h)
164   @headers = @headers.merge(h)
165   return unless @headers.key?("range")
166 
167   @headers.delete("accept-encoding")
168 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
224 def origin
225   @uri.origin
226 end
path()

returnns the URI path of the request uri.

[show source]
    # File lib/httpx/request.rb
204 def path
205   path = uri.path.dup
206   path =  +"" if path.nil?
207   path << "/" if path.empty?
208   path << "?#{query}" unless query.empty?
209   path
210 end
persistent?()
[show source]
    # File lib/httpx/request.rb
137 def persistent?
138   @persistent
139 end
ping!()

marks the request as having been buffered with a ping

[show source]
    # File lib/httpx/request.rb
118 def ping!
119   @ping = true
120 end
ping?()

whether request has been buffered with a ping

[show source]
    # File lib/httpx/request.rb
113 def ping?
114   @ping
115 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
234 def query
235   return @query if defined?(@query)
236 
237   query = []
238   if (q = @query_params) && !q.empty?
239     query << Transcoder::Form.encode(q)
240   end
241   query << @uri.query if @uri.query
242   @query = query.join("&")
243 end
read_timeout()

the read timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
123 def read_timeout
124   @options.timeout[:read_timeout]
125 end
request_timeout()

the request timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
133 def request_timeout
134   @options.timeout[:request_timeout]
135 end
response=(response)

sets the response on this request.

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

the URI scheme of the request uri.

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

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

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

if the request contains trailer headers

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

the write timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
128 def write_timeout
129   @options.timeout[:write_timeout]
130 end