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
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 @persistent = @options.persistent 108 @active_timeouts = [] 109 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 192 def authority 193 @uri.authority 194 end
consumes and returns the next available chunk of request body that can be sent
# 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
whether the request supports the 100-continue handshake and already processed the 100 response.
# File lib/httpx/request.rb 286 def expects? 287 @headers["expect"] == "100-continue" && @informational_status == 100 && !@response 288 end
:nocov:
# 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
returns :r
or :w
, depending on whether the request is waiting for a response or flushing.
# File lib/httpx/request.rb 141 def interests 142 return :r if @state == :done || @state == :expect 143 144 :w 145 end
merges h
into the instance of HTTPX::Headers
of the request.
# File lib/httpx/request.rb 148 def merge_headers(h) 149 @headers = @headers.merge(h) 150 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 200 def origin 201 @uri.origin 202 end
returnns the URI path of the request uri
.
# 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
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 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
the read timeout defined for this requet.
# File lib/httpx/request.rb 112 def read_timeout 113 @options.timeout[:read_timeout] 114 end
the request timeout defined for this requet.
# File lib/httpx/request.rb 122 def request_timeout 123 @options.timeout[:request_timeout] 124 end
sets the response
on this request.
# 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
the URI scheme of the request uri
.
# File lib/httpx/request.rb 153 def scheme 154 @uri.scheme 155 end
# 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
returns an instance of HTTPX::Headers
containing the trailer headers
# File lib/httpx/request.rb 136 def trailers 137 @trailers ||= @options.headers_class.new 138 end
if the request contains trailer headers
# File lib/httpx/request.rb 131 def trailers? 132 defined?(@trailers) 133 end
moves on to the nextstate
of the request state machine (when all preconditions are met)
# 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
the write timeout defined for this requet.
# File lib/httpx/request.rb 117 def write_timeout 118 @options.timeout[:write_timeout] 119 end