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

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

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

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

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

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

:nocov:

[show source]
    # File lib/httpx/request.rb
232 def inspect
233   "#<HTTPX::Request:#{object_id} " \
234     "#{@verb} " \
235     "#{uri} " \
236     "@headers=#{@headers} " \
237     "@body=#{@body}>"
238 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
135 def interests
136   return :r if @state == :done || @state == :expect
137 
138   :w
139 end
merge_headers(h)

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

[show source]
    # File lib/httpx/request.rb
142 def merge_headers(h)
143   @headers = @headers.merge(h)
144 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
194 def origin
195   @uri.origin
196 end
path()

returnns the URI path of the request uri.

[show source]
    # File lib/httpx/request.rb
174 def path
175   path = uri.path.dup
176   path =  +"" if path.nil?
177   path << "/" if path.empty?
178   path << "?#{query}" unless query.empty?
179   path
180 end
persistent?()
[show source]
    # File lib/httpx/request.rb
120 def persistent?
121   @persistent
122 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
204 def query
205   return @query if defined?(@query)
206 
207   query = []
208   if (q = @query_params)
209     query << Transcoder::Form.encode(q)
210   end
211   query << @uri.query if @uri.query
212   @query = query.join("&")
213 end
read_timeout()

the read timeout defined for this requet.

[show source]
    # File lib/httpx/request.rb
106 def read_timeout
107   @options.timeout[:read_timeout]
108 end
request_timeout()

the request timeout defined for this requet.

[show source]
    # File lib/httpx/request.rb
116 def request_timeout
117   @options.timeout[:request_timeout]
118 end
response=(response)

sets the response on this request.

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

the URI scheme of the request uri.

[show source]
    # File lib/httpx/request.rb
147 def scheme
148   @uri.scheme
149 end
trailers()

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

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

if the request contains trailer headers

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

the write timeout defined for this requet.

[show source]
    # File lib/httpx/request.rb
111 def write_timeout
112   @options.timeout[:write_timeout]
113 end