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
USER_AGENT | = | "httpx.rb/#{VERSION}" |
default value used for “user-agent” header, when not overridden. |
Attributes
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 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
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 182 def authority 183 @uri.authority 184 end
consumes and returns the next available chunk of request body that can be sent
# 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
whether the request supports the 100-continue handshake and already processed the 100 response.
# File lib/httpx/request.rb 273 def expects? 274 @headers["expect"] == "100-continue" && @informational_status == 100 && !@response 275 end
:nocov:
# 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
returns :r
or :w
, depending on whether the request is waiting for a response or flushing.
# File lib/httpx/request.rb 131 def interests 132 return :r if @state == :done || @state == :expect 133 134 :w 135 end
merges h
into the instance of HTTPX::Headers
of the request.
# File lib/httpx/request.rb 138 def merge_headers(h) 139 @headers = @headers.merge(h) 140 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 190 def origin 191 @uri.origin 192 end
returnns the URI path of the request uri
.
# 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
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 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
the read timeout defined for this requet.
# File lib/httpx/request.rb 102 def read_timeout 103 @options.timeout[:read_timeout] 104 end
the request timeout defined for this requet.
# File lib/httpx/request.rb 112 def request_timeout 113 @options.timeout[:request_timeout] 114 end
sets the response
on this request.
# 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
the URI scheme of the request uri
.
# File lib/httpx/request.rb 143 def scheme 144 @uri.scheme 145 end
returns an instance of HTTPX::Headers
containing the trailer headers
# File lib/httpx/request.rb 126 def trailers 127 @trailers ||= @options.headers_class.new 128 end
if the request contains trailer headers
# File lib/httpx/request.rb 121 def trailers? 122 defined?(@trailers) 123 end
moves on to the nextstate
of the request state machine (when all preconditions are met)
# 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
the write timeout defined for this requet.
# File lib/httpx/request.rb 107 def write_timeout 108 @options.timeout[:write_timeout] 109 end