Class: HTTP::Request
- Inherits:
-
Object
- Object
- HTTP::Request
- Extended by:
- Forwardable
- Defined in:
- lib/http/request.rb,
lib/http/request/body.rb,
lib/http/request/proxy.rb,
lib/http/request/writer.rb,
lib/http/request/builder.rb,
sig/http.rbs
Overview
Represents an HTTP request with verb, URI, headers, and body
Defined Under Namespace
Modules: Proxy Classes: Body, Builder, UnsupportedMethodError, UnsupportedSchemeError, Writer
Constant Summary collapse
- USER_AGENT =
Default User-Agent header value
"http.rb/#{HTTP::VERSION}".freeze
- METHODS =
Supported HTTP methods
[ # RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 :options, :get, :head, :post, :put, :delete, :trace, :connect, # RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV :propfind, :proppatch, :mkcol, :copy, :move, :lock, :unlock, # RFC 3648: WebDAV Ordered Collections Protocol :orderpatch, # RFC 3744: WebDAV Access Control Protocol :acl, # RFC 6352: vCard Extensions to WebDAV -- CardDAV :report, # RFC 5789: PATCH Method for HTTP :patch, # draft-reschke-webdav-search: WebDAV Search :search, # RFC 4791: Calendaring Extensions to WebDAV -- CalDAV :mkcalendar, # Implemented by several caching servers, like Squid, Varnish or Fastly :purge ].freeze
- SCHEMES =
Allowed schemes
%i[http https ws wss].freeze
- PORTS =
Default ports of supported schemes
{ http: 80, https: 443, ws: 80, wss: 443 }.freeze
Instance Attribute Summary collapse
-
#body ⇒ HTTP::Request::Body
readonly
Request body object.
-
#headers ⇒ HTTP::Headers
readonly
The HTTP headers collection.
-
#host ⇒ String
readonly
private
Host from the URI.
-
#proxy ⇒ Hash
readonly
Proxy configuration hash.
-
#scheme ⇒ Symbol
readonly
URI scheme as a lowercase symbol.
-
#uri ⇒ HTTP::URI
readonly
Request URI.
-
#uri_normalizer ⇒ #call
readonly
URI normalizer callable.
-
#verb ⇒ Symbol
readonly
HTTP method as a lowercase symbol.
-
#version ⇒ String
readonly
HTTP version string.
Instance Method Summary collapse
-
#default_host_header_value ⇒ String
private
Build default Host header value.
-
#headline ⇒ String
Compute HTTP request header for direct or proxy request.
-
#initialize(verb:, uri:, headers: nil, proxy: {}, body: nil, version: "1.1", uri_normalizer: nil) ⇒ HTTP::Request
constructor
Create a new HTTP request.
-
#inspect ⇒ String
Human-readable representation of base request info.
-
#parse_uri!(uri) ⇒ void
private
Parse and normalize the URI, setting scheme.
-
#port ⇒ Fixnum
private
Return the port for the request URI.
-
#prepare_body(body) ⇒ HTTP::Request::Body
private
Coerce input into a Body object.
-
#prepare_headers(headers) ⇒ HTTP::Headers
private
Build headers with default values.
-
#redirect(uri, verb = @verb) ⇒ HTTP::Request
Returns new Request with updated uri.
-
#redirect_headers(redirect_uri, verb) ⇒ HTTP::Headers
private
Build headers for a redirect request.
-
#socket_host ⇒ String
Host for tcp socket.
-
#socket_port ⇒ Integer
Port for tcp socket.
-
#stream(socket) ⇒ void
Stream the request to a socket.
-
#using_authenticated_proxy? ⇒ Boolean
Is this request using an authenticated proxy?.
-
#using_proxy? ⇒ Boolean
Is this request using a proxy?.
-
#validate_method_and_scheme! ⇒ void
private
Validate HTTP method and URI scheme.
Methods included from Proxy
#connect_using_proxy, #encode64, #include_proxy_authorization_header, #include_proxy_headers, #proxy_authorization_header, #proxy_connect_header, #proxy_connect_headers
Methods included from Base64
Constructor Details
#initialize(verb:, uri:, headers: nil, proxy: {}, body: nil, version: "1.1", uri_normalizer: nil) ⇒ HTTP::Request
Create a new HTTP request
160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/http/request.rb', line 160 def initialize(verb:, uri:, headers: nil, proxy: {}, body: nil, version: "1.1", uri_normalizer: nil) @uri_normalizer = uri_normalizer || HTTP::URI::NORMALIZER @verb = verb.to_s.downcase.to_sym parse_uri!(uri) validate_method_and_scheme! @proxy = proxy @version = version @headers = prepare_headers(headers) @body = prepare_body(body) end |
Instance Attribute Details
#body ⇒ HTTP::Request::Body (readonly)
Request body object
125 126 127 |
# File 'lib/http/request.rb', line 125 def body @body end |
#headers ⇒ HTTP::Headers (readonly)
The HTTP headers collection
134 135 136 |
# File 'lib/http/request.rb', line 134 def headers @headers end |
#host ⇒ String (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Host from the URI
316 |
# File 'lib/http/request.rb', line 316 def_delegator :@uri, :host |
#proxy ⇒ Hash (readonly)
Proxy configuration hash
116 117 118 |
# File 'lib/http/request.rb', line 116 def proxy @proxy end |
#scheme ⇒ Symbol (readonly)
URI scheme as a lowercase symbol
89 90 91 |
# File 'lib/http/request.rb', line 89 def scheme @scheme end |
#uri ⇒ HTTP::URI (readonly)
Request URI
107 108 109 |
# File 'lib/http/request.rb', line 107 def uri @uri end |
#uri_normalizer ⇒ #call (readonly)
URI normalizer callable
98 99 100 |
# File 'lib/http/request.rb', line 98 def uri_normalizer @uri_normalizer end |
#verb ⇒ Symbol (readonly)
HTTP method as a lowercase symbol
80 81 82 |
# File 'lib/http/request.rb', line 80 def verb @verb end |
#version ⇒ String (readonly)
HTTP version string
143 144 145 |
# File 'lib/http/request.rb', line 143 def version @version end |
Instance Method Details
#default_host_header_value ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build default Host header value
328 329 330 331 332 333 334 |
# File 'lib/http/request.rb', line 328 def default_host_header_value value = PORTS[@scheme] == port ? host : "#{host}:#{port}" raise RequestError, "Invalid host: #{value.inspect}" if value.match?(/\s/) value end |
#headline ⇒ String
Compute HTTP request header for direct or proxy request
237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/http/request.rb', line 237 def headline request_uri = if using_proxy? && !uri.https? uri.omit(:fragment) else uri.request_uri end.to_s raise RequestError, "Invalid request URI: #{request_uri.inspect}" if request_uri.match?(/\s/) "#{verb.to_s.upcase} #{request_uri} HTTP/#{version}" end |
#inspect ⇒ String
Human-readable representation of base request info
281 282 283 |
# File 'lib/http/request.rb', line 281 def inspect format("#<%s/%s %s %s>", self.class, @version, String(verb).upcase, uri) end |
#parse_uri!(uri) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Parse and normalize the URI, setting scheme
339 340 341 342 343 344 345 |
# File 'lib/http/request.rb', line 339 def parse_uri!(uri) raise ArgumentError, "uri is nil" if uri.nil? raise ArgumentError, "uri is empty" if uri.is_a?(String) && uri.empty? @uri = @uri_normalizer.call(uri) @scheme = String(@uri.scheme).downcase.to_sym if @uri.scheme end |
#port ⇒ Fixnum
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return the port for the request URI
321 322 323 |
# File 'lib/http/request.rb', line 321 def port @uri.port || @uri.default_port end |
#prepare_body(body) ⇒ HTTP::Request::Body
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Coerce input into a Body object
359 360 361 |
# File 'lib/http/request.rb', line 359 def prepare_body(body) body.is_a?(Body) ? body : Body.new(body) end |
#prepare_headers(headers) ⇒ HTTP::Headers
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build headers with default values
366 367 368 369 370 371 372 373 |
# File 'lib/http/request.rb', line 366 def prepare_headers(headers) headers = Headers.coerce(headers || {}) headers[Headers::HOST] ||= default_host_header_value headers[Headers::USER_AGENT] ||= USER_AGENT headers end |
#redirect(uri, verb = @verb) ⇒ HTTP::Request
Returns new Request with updated uri
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/http/request.rb', line 180 def redirect(uri, verb = @verb) redirect_uri = @uri.join(uri) headers = redirect_headers(redirect_uri, verb) new_body = verb == :get ? nil : body.source self.class.new( verb: verb, uri: redirect_uri, headers: headers, proxy: proxy, body: new_body, version: version, uri_normalizer: uri_normalizer ) end |
#redirect_headers(redirect_uri, verb) ⇒ HTTP::Headers
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build headers for a redirect request
Strips the Host header (it will be regenerated), sensitive credentials on cross-origin redirects, and Content-Type on GET verb changes.
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/http/request.rb', line 296 def redirect_headers(redirect_uri, verb) headers = self.headers.dup headers.delete(Headers::HOST) # Strip sensitive headers when redirecting to a different origin # (scheme + host + port) to prevent credential leakage. unless @uri.origin == redirect_uri.origin headers.delete(Headers::AUTHORIZATION) headers.delete(Headers::COOKIE) end headers.delete(Headers::CONTENT_TYPE) if verb == :get headers end |
#socket_host ⇒ String
Host for tcp socket
257 258 259 |
# File 'lib/http/request.rb', line 257 def socket_host using_proxy? ? proxy[:proxy_address] : host end |
#socket_port ⇒ Integer
Port for tcp socket
268 269 270 |
# File 'lib/http/request.rb', line 268 def socket_port using_proxy? ? proxy[:proxy_port] : port end |
#stream(socket) ⇒ void
This method returns an undefined value.
Stream the request to a socket
203 204 205 206 |
# File 'lib/http/request.rb', line 203 def stream(socket) include_proxy_headers if using_proxy? && !@uri.https? Request::Writer.new(socket, body, headers, headline).stream end |
#using_authenticated_proxy? ⇒ Boolean
Is this request using an authenticated proxy?
226 227 228 |
# File 'lib/http/request.rb', line 226 def using_authenticated_proxy? proxy && proxy.keys.size >= 4 end |
#using_proxy? ⇒ Boolean
Is this request using a proxy?
215 216 217 |
# File 'lib/http/request.rb', line 215 def using_proxy? proxy && proxy.keys.size >= 2 end |
#validate_method_and_scheme! ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Validate HTTP method and URI scheme
350 351 352 353 354 |
# File 'lib/http/request.rb', line 350 def validate_method_and_scheme! raise(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb) raise(HTTP::URI::InvalidError, "invalid URI: #{@uri}") unless @scheme raise(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme) end |