Class: HTTP::Client
- Inherits:
-
Object
- Object
- HTTP::Client
- Extended by:
- Forwardable
- Includes:
- Chainable
- Defined in:
- lib/http/client.rb,
sig/http.rbs
Overview
Clients make requests and receive responses
Constant Summary
Constants included from Chainable
HTTP::Chainable::PROXY_ARG_MAP
Instance Method Summary collapse
-
#around_request(request, options) {|arg0| ... } ⇒ HTTP::Response
private
Compose around_request chains from all features.
-
#build_response(req, options) ⇒ HTTP::Response
private
Build a response from the current connection.
-
#build_wrapped_response(req, options) ⇒ HTTP::Response
private
Build response and apply feature wrapping.
-
#close ⇒ void
Close the connection and reset state.
-
#initialize(default_options = nil) ⇒ HTTP::Client
constructor
Initialize a new HTTP Client.
-
#notify_features(req, options) ⇒ void
private
Notify features of an upcoming request attempt.
-
#perform(req, options) ⇒ HTTP::Response
Perform a single (no follow) HTTP request.
-
#perform_exchange(req, options) ⇒ HTTP::Response
private
Execute the HTTP exchange wrapped by feature around_request hooks.
-
#perform_once(req, options) ⇒ HTTP::Response
private
Execute a single HTTP request without retry logic.
-
#perform_with_retry(req, options) ⇒ HTTP::Response
private
Execute a request with retry logic.
-
#persistent? ⇒ Boolean
Indicate whether the client has persistent connections.
-
#request(verb, uri, headers: nil, params: nil, form: nil, json: nil, body: nil, response: nil, encoding: nil, follow: nil, ssl: nil, ssl_context: nil, proxy: nil, nodelay: nil, features: nil, retriable: nil, socket_class: nil, ssl_socket_class: nil, timeout_class: nil, timeout_options: nil, keep_alive_timeout: nil, base_uri: nil, persistent: nil) ⇒ HTTP::Response
Make an HTTP request.
-
#send_request(req, options) ⇒ void
private
Send request over the connection, handling proxy and errors.
-
#verify_connection!(uri) ⇒ void
private
Verify our request isn't going to be made against another URI.
Methods included from Chainable
#accept, #auth, #base_uri, #basic_auth, #branch, #build_proxy_hash, #cookies, #default_options, #default_options=, #digest_auth, #encoding, #follow, #headers, #make_client, #nodelay, #persistent, #resolve_global_only, #resolve_timeout_hash, #retriable, #timeout, #use, #via
Methods included from HTTP::Chainable::Verbs
#connect, #delete, #get, #head, #options, #patch, #post, #put, #trace
Methods included from Base64
Constructor Details
#initialize(default_options = nil) ⇒ HTTP::Client
Initialize a new HTTP Client
30 31 32 33 34 |
# File 'lib/http/client.rb', line 30 def initialize( = nil, **) @default_options = HTTP::Options.new(, **) @connection = nil @state = :clean end |
Instance Method Details
#around_request(request, options) {|arg0| ... } ⇒ HTTP::Response
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.
Compose around_request chains from all features
191 192 193 194 195 |
# File 'lib/http/client.rb', line 191 def around_request(request, , &block) .features.values.reverse.reduce(block) do |inner, feature| ->(req) { feature.around_request(req) { |r| inner.call(r) } } end.call(request) end |
#build_response(req, options) ⇒ HTTP::Response
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 a response from the current connection
200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/http/client.rb', line 200 def build_response(req, ) Response.new( status: @connection.status_code, version: @connection.http_version, headers: @connection.headers, proxy_headers: @connection.proxy_response_headers, connection: @connection, encoding: .encoding, request: req ).tap { |res| @connection.pending_response = res } end |
#build_wrapped_response(req, options) ⇒ HTTP::Response
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 response and apply feature wrapping
161 162 163 164 165 166 167 |
# File 'lib/http/client.rb', line 161 def build_wrapped_response(req, ) res = build_response(req, ) .features.values.reverse.inject(res) do |response, feature| feature.wrap_response(response) end end |
#close ⇒ void
This method returns an undefined value.
Close the connection and reset state
103 104 105 106 107 |
# File 'lib/http/client.rb', line 103 def close @connection&.close @connection = nil @state = :clean end |
#notify_features(req, options) ⇒ 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.
Notify features of an upcoming request attempt
172 173 174 |
# File 'lib/http/client.rb', line 172 def notify_features(req, ) .features.each_value { |feature| feature.on_request(req) } end |
#perform(req, options) ⇒ HTTP::Response
Perform a single (no follow) HTTP request
88 89 90 91 92 93 94 |
# File 'lib/http/client.rb', line 88 def perform(req, ) if .retriable perform_with_retry(req, ) else perform_once(req, ) end end |
#perform_exchange(req, options) ⇒ HTTP::Response
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.
Execute the HTTP exchange wrapped by feature around_request hooks
179 180 181 182 183 184 185 186 |
# File 'lib/http/client.rb', line 179 def perform_exchange(req, ) around_request(req, ) do |request| verify_connection!(request.uri) @state = :dirty send_request(request, ) build_wrapped_response(request, ) end end |
#perform_once(req, options) ⇒ HTTP::Response
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.
Execute a single HTTP request without retry logic
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/http/client.rb', line 117 def perform_once(req, ) res = perform_exchange(req, ) @connection.finish_response if res.request.verb == :head @state = :clean res rescue close raise end |
#perform_with_retry(req, options) ⇒ HTTP::Response
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.
Execute a request with retry logic
135 136 137 138 139 |
# File 'lib/http/client.rb', line 135 def perform_with_retry(req, ) Retriable::Performer.new(**.retriable).perform(self, req) do perform_once(req, ) end end |
#persistent? ⇒ Boolean
Indicate whether the client has persistent connections
77 |
# File 'lib/http/client.rb', line 77 def_delegator :default_options, :persistent? |
#request(verb, uri, headers: nil, params: nil, form: nil, json: nil, body: nil, response: nil, encoding: nil, follow: nil, ssl: nil, ssl_context: nil, proxy: nil, nodelay: nil, features: nil, retriable: nil, socket_class: nil, ssl_socket_class: nil, timeout_class: nil, timeout_options: nil, keep_alive_timeout: nil, base_uri: nil, persistent: nil) ⇒ HTTP::Response
Make an HTTP request
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/http/client.rb', line 45 def request(verb, uri, headers: nil, params: nil, form: nil, json: nil, body: nil, response: nil, encoding: nil, follow: nil, ssl: nil, ssl_context: nil, proxy: nil, nodelay: nil, features: nil, retriable: nil, socket_class: nil, ssl_socket_class: nil, timeout_class: nil, timeout_options: nil, keep_alive_timeout: nil, base_uri: nil, persistent: nil) opts = { headers: headers, params: params, form: form, json: json, body: body, response: response, encoding: encoding, follow: follow, ssl: ssl, ssl_context: ssl_context, proxy: proxy, nodelay: nodelay, features: features, retriable: retriable, socket_class: socket_class, ssl_socket_class: ssl_socket_class, timeout_class: timeout_class, timeout_options: , keep_alive_timeout: keep_alive_timeout, base_uri: base_uri, persistent: persistent }.compact opts = @default_options.merge(opts) builder = Request::Builder.new(opts) req = builder.build(verb, uri) res = perform(req, opts) return res unless opts.follow Redirector.new(**opts.follow).perform(req, res) do |request| perform(builder.wrap(request), opts) end end |
#send_request(req, options) ⇒ 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.
Send request over the connection, handling proxy and errors
144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/http/client.rb', line 144 def send_request(req, ) notify_features(req, ) @connection ||= HTTP::Connection.new(req, ) unless @connection.failed_proxy_connect? @connection.send_request(req) @connection.read_headers! end rescue Error => e .features.each_value { |feature| feature.on_error(req, e) } raise end |
#verify_connection!(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.
Verify our request isn't going to be made against another URI
216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/http/client.rb', line 216 def verify_connection!(uri) if .persistent? && uri.origin != .persistent raise StateError, "Persistence is enabled for #{.persistent}, but we got #{uri.origin}" end # We re-create the connection object because we want to let prior requests # lazily load the body as long as possible, and this mimics prior functionality. return close if @connection && (!@connection.keep_alive? || @connection.expired?) # If we get into a bad state (eg, Timeout.timeout ensure being killed) # close the connection to prevent potential for mixed responses. close if @state == :dirty end |