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

USER_AGENT = "httpx.rb/#{VERSION}".freeze  

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

Attributes

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
63 def initialize(verb, uri, options, params = EMPTY_HASH)
64   @verb    = verb.to_s.upcase
65   @uri     = Utils.to_uri(uri)
66 
67   @headers = options.headers.dup
68   merge_headers(params.delete(:headers)) if params.key?(:headers)
69 
70   @headers["user-agent"] ||= USER_AGENT
71   @headers["accept"]     ||= "*/*"
72 
73   # forego compression in the Range request case
74   if @headers.key?("range")
75     @headers.delete("accept-encoding")
76   else
77     @headers["accept-encoding"] ||= options.supported_compression_formats
78   end
79 
80   @query_params = params.delete(:params) if params.key?(:params)
81 
82   @body = options.request_body_class.new(@headers, options, **params)
83 
84   @options = @body.options
85 
86   if @uri.relative? || @uri.host.nil?
87     origin = @options.origin
88     raise(Error, "invalid URI: #{@uri}") unless origin
89 
90     base_path = @options.base_path
91 
92     @uri = origin.merge("#{base_path}#{@uri}")
93   end
94 
95   @state = :idle
96   @response = nil
97   @peer_address = nil
98   @persistent = @options.persistent
99 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
182 def authority
183   @uri.authority
184 end
drain_body()

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

[show source]
    # File lib/httpx/request.rb
212 def drain_body
213   return nil if @body.nil?
214 
215   @drainer ||= @body.each
216   chunk = @drainer.next.dup
217 
218   emit(:body_chunk, chunk)
219   chunk
220 rescue StopIteration
221   nil
222 rescue StandardError => e
223   @drain_error = e
224   nil
225 end
expects?()

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

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

:nocov:

[show source]
    # File lib/httpx/request.rb
228 def inspect
229   "#<HTTPX::Request:#{object_id} " \
230     "#{@verb} " \
231     "#{uri} " \
232     "@headers=#{@headers} " \
233     "@body=#{@body}>"
234 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
131 def interests
132   return :r if @state == :done || @state == :expect
133 
134   :w
135 end
merge_headers(h)

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

[show source]
    # File lib/httpx/request.rb
138 def merge_headers(h)
139   @headers = @headers.merge(h)
140 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
190 def origin
191   @uri.origin
192 end
path()

returnns the URI path of the request uri.

[show source]
    # File lib/httpx/request.rb
170 def path
171   path = uri.path.dup
172   path =  +"" if path.nil?
173   path << "/" if path.empty?
174   path << "?#{query}" unless query.empty?
175   path
176 end
persistent?()
[show source]
    # File lib/httpx/request.rb
116 def persistent?
117   @persistent
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
200 def query
201   return @query if defined?(@query)
202 
203   query = []
204   if (q = @query_params)
205     query << Transcoder::Form.encode(q)
206   end
207   query << @uri.query if @uri.query
208   @query = query.join("&")
209 end
read_timeout()

the read timeout defined for this requet.

[show source]
    # File lib/httpx/request.rb
102 def read_timeout
103   @options.timeout[:read_timeout]
104 end
request_timeout()

the request timeout defined for this requet.

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

sets the response on this request.

[show source]
    # File lib/httpx/request.rb
148 def response=(response)
149   return unless response
150 
151   if response.is_a?(Response) && response.status < 200
152     # deal with informational responses
153 
154     if response.status == 100 && @headers.key?("expect")
155       @informational_status = response.status
156       return
157     end
158 
159     # 103 Early Hints advertises resources in document to browsers.
160     # not very relevant for an HTTP client, discard.
161     return if response.status >= 103
162   end
163 
164   @response = response
165 
166   emit(:response_started, response)
167 end
scheme()

the URI scheme of the request uri.

[show source]
    # File lib/httpx/request.rb
143 def scheme
144   @uri.scheme
145 end
trailers()

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

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

if the request contains trailer headers

[show source]
    # File lib/httpx/request.rb
121 def trailers?
122   defined?(@trailers)
123 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
238 def transition(nextstate)
239   case nextstate
240   when :idle
241     @body.rewind
242     @response = nil
243     @drainer = nil
244   when :headers
245     return unless @state == :idle
246   when :body
247     return unless @state == :headers ||
248                   @state == :expect
249 
250     if @headers.key?("expect")
251       if @informational_status && @informational_status == 100
252         # check for 100 Continue response, and deallocate the var
253         # if @informational_status == 100
254         #   @response = nil
255         # end
256       else
257         return if @state == :expect # do not re-set it
258 
259         nextstate = :expect
260       end
261     end
262   when :trailers
263     return unless @state == :body
264   when :done
265     return if @state == :expect
266   end
267   @state = nextstate
268   emit(@state, self)
269   nil
270 end
write_timeout()

the write timeout defined for this requet.

[show source]
    # File lib/httpx/request.rb
107 def write_timeout
108   @options.timeout[:write_timeout]
109 end