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

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

[show source]
    # File lib/httpx/request.rb
237 def drain_body
238   return nil if @body.nil?
239 
240   @drainer ||= @body.each
241   chunk = @drainer.next.dup
242 
243   emit(:body_chunk, chunk)
244   chunk
245 rescue StopIteration
246   nil
247 rescue StandardError => e
248   @drain_error = e
249   nil
250 end
expects?()

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

[show source]
    # File lib/httpx/request.rb
303 def expects?
304   @headers["expect"] == "100-continue" && @informational_status == 100 && !@response
305 end
inspect()

:nocov:

[show source]
    # File lib/httpx/request.rb
253 def inspect
254   "#<#{self.class}:#{object_id} " \
255     "#{@verb} " \
256     "#{uri} " \
257     "@headers=#{@headers} " \
258     "@body=#{@body}>"
259 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
143 def interests
144   return :r if @state == :done || @state == :expect
145 
146   :w
147 end
merge_headers(h)

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

[show source]
    # File lib/httpx/request.rb
154 def merge_headers(h)
155   @headers = @headers.merge(h)
156   return unless @headers.key?("range")
157 
158   @headers.delete("accept-encoding")
159 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
215 def origin
216   @uri.origin
217 end
path()

returnns the URI path of the request uri.

[show source]
    # File lib/httpx/request.rb
195 def path
196   path = uri.path.dup
197   path =  +"" if path.nil?
198   path << "/" if path.empty?
199   path << "?#{query}" unless query.empty?
200   path
201 end
persistent?()
[show source]
    # File lib/httpx/request.rb
128 def persistent?
129   @persistent
130 end
ping!()

marks the request as having been buffered with a ping

[show source]
    # File lib/httpx/request.rb
109 def ping!
110   @ping = true
111 end
ping?()

whether request has been buffered with a ping

[show source]
    # File lib/httpx/request.rb
104 def ping?
105   @ping
106 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
225 def query
226   return @query if defined?(@query)
227 
228   query = []
229   if (q = @query_params) && !q.empty?
230     query << Transcoder::Form.encode(q)
231   end
232   query << @uri.query if @uri.query
233   @query = query.join("&")
234 end
read_timeout()

the read timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
114 def read_timeout
115   @options.timeout[:read_timeout]
116 end
request_timeout()

the request timeout defined for this request.

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

sets the response on this request.

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

the URI scheme of the request uri.

[show source]
    # File lib/httpx/request.rb
162 def scheme
163   @uri.scheme
164 end
set_timeout_callback(event, &callback)
[show source]
    # File lib/httpx/request.rb
307 def set_timeout_callback(event, &callback)
308   clb = once(event, &callback)
309 
310   # reset timeout callbacks when requests get rerouted to a different connection
311   once(:idle) do
312     callbacks(event).delete(clb)
313   end
314 end
trailers()

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

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

if the request contains trailer headers

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

the write timeout defined for this request.

[show source]
    # File lib/httpx/request.rb
119 def write_timeout
120   @options.timeout[:write_timeout]
121 end