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

Classes and Modules

  1. HTTPX::Request::Body

Constants

ALLOWED_URI_SCHEMES = %w[https http].freeze  
USER_AGENT = "httpx.rb/#{VERSION}".freeze  

default value used for “user-agent” header, when not overridden.

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
 70 def initialize(verb, uri, options, params = EMPTY_HASH)
 71   @verb    = verb.to_s.upcase
 72   @uri     = Utils.to_uri(uri)
 73 
 74   @headers = options.headers.dup
 75   merge_headers(params.delete(:headers)) if params.key?(:headers)
 76 
 77   @headers["user-agent"] ||= USER_AGENT
 78   @headers["accept"]     ||= "*/*"
 79 
 80   # forego compression in the Range request case
 81   if @headers.key?("range")
 82     @headers.delete("accept-encoding")
 83   else
 84     @headers["accept-encoding"] ||= options.supported_compression_formats
 85   end
 86 
 87   @query_params = params.delete(:params) if params.key?(:params)
 88 
 89   @body = options.request_body_class.new(@headers, options, **params)
 90 
 91   @options = @body.options
 92 
 93   if @uri.relative? || @uri.host.nil?
 94     origin = @options.origin
 95     raise(Error, "invalid URI: #{@uri}") unless origin
 96 
 97     base_path = @options.base_path
 98 
 99     @uri = origin.merge("#{base_path}#{@uri}")
100   end
101 
102   raise UnsupportedSchemeError, "#{@uri}: #{@uri.scheme}: unsupported URI scheme" unless ALLOWED_URI_SCHEMES.include?(@uri.scheme)
103 
104   @state = :idle
105   @response = nil
106   @peer_address = nil
107   @persistent = @options.persistent
108   @active_timeouts = []
109 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
192 def authority
193   @uri.authority
194 end
drain_body()

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

[show source]
    # File lib/httpx/request.rb
222 def drain_body
223   return nil if @body.nil?
224 
225   @drainer ||= @body.each
226   chunk = @drainer.next.dup
227 
228   emit(:body_chunk, chunk)
229   chunk
230 rescue StopIteration
231   nil
232 rescue StandardError => e
233   @drain_error = e
234   nil
235 end
expects?()

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

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

:nocov:

[show source]
    # File lib/httpx/request.rb
238 def inspect
239   "#<HTTPX::Request:#{object_id} " \
240     "#{@verb} " \
241     "#{uri} " \
242     "@headers=#{@headers} " \
243     "@body=#{@body}>"
244 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
141 def interests
142   return :r if @state == :done || @state == :expect
143 
144   :w
145 end
merge_headers(h)

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

[show source]
    # File lib/httpx/request.rb
148 def merge_headers(h)
149   @headers = @headers.merge(h)
150 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
200 def origin
201   @uri.origin
202 end
path()

returnns the URI path of the request uri.

[show source]
    # File lib/httpx/request.rb
180 def path
181   path = uri.path.dup
182   path =  +"" if path.nil?
183   path << "/" if path.empty?
184   path << "?#{query}" unless query.empty?
185   path
186 end
persistent?()
[show source]
    # File lib/httpx/request.rb
126 def persistent?
127   @persistent
128 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
210 def query
211   return @query if defined?(@query)
212 
213   query = []
214   if (q = @query_params)
215     query << Transcoder::Form.encode(q)
216   end
217   query << @uri.query if @uri.query
218   @query = query.join("&")
219 end
read_timeout()

the read timeout defined for this requet.

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

the request timeout defined for this requet.

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

sets the response on this request.

[show source]
    # File lib/httpx/request.rb
158 def response=(response)
159   return unless response
160 
161   if response.is_a?(Response) && response.status < 200
162     # deal with informational responses
163 
164     if response.status == 100 && @headers.key?("expect")
165       @informational_status = response.status
166       return
167     end
168 
169     # 103 Early Hints advertises resources in document to browsers.
170     # not very relevant for an HTTP client, discard.
171     return if response.status >= 103
172   end
173 
174   @response = response
175 
176   emit(:response_started, response)
177 end
scheme()

the URI scheme of the request uri.

[show source]
    # File lib/httpx/request.rb
153 def scheme
154   @uri.scheme
155 end
set_timeout_callback(event, &callback)
[show source]
    # File lib/httpx/request.rb
290 def set_timeout_callback(event, &callback)
291   clb = once(event, &callback)
292 
293   # reset timeout callbacks when requests get rerouted to a different connection
294   once(:idle) do
295     callbacks(event).delete(clb)
296   end
297 end
trailers()

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

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

if the request contains trailer headers

[show source]
    # File lib/httpx/request.rb
131 def trailers?
132   defined?(@trailers)
133 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
248 def transition(nextstate)
249   case nextstate
250   when :idle
251     @body.rewind
252     @response = nil
253     @drainer = nil
254     @active_timeouts.clear
255   when :headers
256     return unless @state == :idle
257 
258   when :body
259     return unless @state == :headers ||
260                   @state == :expect
261 
262     if @headers.key?("expect")
263       if @informational_status && @informational_status == 100
264         # check for 100 Continue response, and deallocate the var
265         # if @informational_status == 100
266         #   @response = nil
267         # end
268       else
269         return if @state == :expect # do not re-set it
270 
271         nextstate = :expect
272       end
273     end
274   when :trailers
275     return unless @state == :body
276   when :done
277     return if @state == :expect
278 
279   end
280   @state = nextstate
281   emit(@state, self)
282   nil
283 end
write_timeout()

the write timeout defined for this requet.

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