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.
Methods
Public Class
Public Instance
- active_timeouts
- authority
- body
- can_buffer?
- drain_body
- drain_error
- expects?
- headers
- inspect
- interests
- merge_headers
- options
- origin
- path
- peer_address
- persistent
- persistent?
- ping!
- ping?
- query
- read_timeout
- request_timeout
- response
- response=
- scheme
- set_timeout_callback
- state
- trailers
- trailers?
- transition
- uri
- verb
- write_timeout
Included modules
Classes and Modules
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 |
drain_error | [R] |
Exception raised during enumerable body writes. |
headers | [R] |
an |
options | [R] |
an |
peer_address | [RW] |
The IP address from the peer server. |
persistent | [W] | |
response | [R] |
the corresponding |
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
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.
# 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 @ping = false 108 @persistent = @options.persistent 109 @active_timeouts = [] 110 end
Public Instance methods
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"
# File lib/httpx/request.rb 207 def authority 208 @uri.authority 209 end
# File lib/httpx/request.rb 158 def can_buffer? 159 @state != :done 160 end
consumes and returns the next available chunk of request body that can be sent
# 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
whether the request supports the 100-continue handshake and already processed the 100 response.
# File lib/httpx/request.rb 302 def expects? 303 @headers["expect"] == "100-continue" && @informational_status == 100 && !@response 304 end
:nocov:
# 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
returns :r
or :w
, depending on whether the request is waiting for a response or flushing.
# File lib/httpx/request.rb 152 def interests 153 return :r if @state == :done || @state == :expect 154 155 :w 156 end
merges h
into the instance of HTTPX::Headers
of the request.
# File lib/httpx/request.rb 163 def merge_headers(h) 164 @headers = @headers.merge(h) 165 end
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"
# File lib/httpx/request.rb 215 def origin 216 @uri.origin 217 end
returnns the URI path of the request uri
.
# 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
marks the request as having been buffered with a ping
# File lib/httpx/request.rb 118 def ping! 119 @ping = true 120 end
whether request has been buffered with a ping
# File lib/httpx/request.rb 113 def ping? 114 @ping 115 end
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"
# 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
the read timeout defined for this request.
# File lib/httpx/request.rb 123 def read_timeout 124 @options.timeout[:read_timeout] 125 end
the request timeout defined for this request.
# File lib/httpx/request.rb 133 def request_timeout 134 @options.timeout[:request_timeout] 135 end
sets the response
on this request.
# File lib/httpx/request.rb 173 def response=(response) 174 return unless response 175 176 if response.is_a?(Response) && response.status < 200 177 # deal with informational responses 178 179 if response.status == 100 && @headers.key?("expect") 180 @informational_status = response.status 181 return 182 end 183 184 # 103 Early Hints advertises resources in document to browsers. 185 # not very relevant for an HTTP client, discard. 186 return if response.status >= 103 187 end 188 189 @response = response 190 191 emit(:response_started, response) 192 end
the URI scheme of the request uri
.
# File lib/httpx/request.rb 168 def scheme 169 @uri.scheme 170 end
# File lib/httpx/request.rb 306 def set_timeout_callback(event, &callback) 307 clb = once(event, &callback) 308 309 # reset timeout callbacks when requests get rerouted to a different connection 310 once(:idle) do 311 callbacks(event).delete(clb) 312 end 313 end
returns an instance of HTTPX::Headers
containing the trailer headers
# File lib/httpx/request.rb 147 def trailers 148 @trailers ||= @options.headers_class.new 149 end
if the request contains trailer headers
# File lib/httpx/request.rb 142 def trailers? 143 defined?(@trailers) 144 end
moves on to the nextstate
of the request state machine (when all preconditions are met)
# 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 @state = nextstate 297 emit(@state, self) 298 nil 299 end
the write timeout defined for this request.
# File lib/httpx/request.rb 128 def write_timeout 129 @options.timeout[:write_timeout] 130 end