http 6.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +267 -0
- data/CONTRIBUTING.md +26 -0
- data/LICENSE.txt +20 -0
- data/README.md +263 -0
- data/SECURITY.md +17 -0
- data/UPGRADING.md +491 -0
- data/http.gemspec +48 -0
- data/lib/http/base64.rb +22 -0
- data/lib/http/chainable/helpers.rb +62 -0
- data/lib/http/chainable/verbs.rb +136 -0
- data/lib/http/chainable.rb +377 -0
- data/lib/http/client.rb +230 -0
- data/lib/http/connection/internals.rb +141 -0
- data/lib/http/connection.rb +265 -0
- data/lib/http/content_type.rb +89 -0
- data/lib/http/errors.rb +67 -0
- data/lib/http/feature.rb +86 -0
- data/lib/http/features/auto_deflate.rb +230 -0
- data/lib/http/features/auto_inflate.rb +64 -0
- data/lib/http/features/caching/entry.rb +178 -0
- data/lib/http/features/caching/in_memory_store.rb +63 -0
- data/lib/http/features/caching.rb +216 -0
- data/lib/http/features/digest_auth.rb +234 -0
- data/lib/http/features/instrumentation.rb +149 -0
- data/lib/http/features/logging.rb +231 -0
- data/lib/http/features/normalize_uri.rb +34 -0
- data/lib/http/features/raise_error.rb +37 -0
- data/lib/http/form_data/composite_io.rb +106 -0
- data/lib/http/form_data/file.rb +95 -0
- data/lib/http/form_data/multipart/param.rb +62 -0
- data/lib/http/form_data/multipart.rb +106 -0
- data/lib/http/form_data/part.rb +52 -0
- data/lib/http/form_data/readable.rb +58 -0
- data/lib/http/form_data/urlencoded.rb +175 -0
- data/lib/http/form_data/version.rb +8 -0
- data/lib/http/form_data.rb +102 -0
- data/lib/http/headers/known.rb +90 -0
- data/lib/http/headers/normalizer.rb +50 -0
- data/lib/http/headers.rb +343 -0
- data/lib/http/mime_type/adapter.rb +43 -0
- data/lib/http/mime_type/json.rb +41 -0
- data/lib/http/mime_type.rb +96 -0
- data/lib/http/options/definitions.rb +189 -0
- data/lib/http/options.rb +241 -0
- data/lib/http/redirector.rb +157 -0
- data/lib/http/request/body.rb +181 -0
- data/lib/http/request/builder.rb +184 -0
- data/lib/http/request/proxy.rb +83 -0
- data/lib/http/request/writer.rb +186 -0
- data/lib/http/request.rb +375 -0
- data/lib/http/response/body.rb +172 -0
- data/lib/http/response/inflater.rb +60 -0
- data/lib/http/response/parser.rb +223 -0
- data/lib/http/response/status/reasons.rb +79 -0
- data/lib/http/response/status.rb +263 -0
- data/lib/http/response.rb +350 -0
- data/lib/http/retriable/delay_calculator.rb +91 -0
- data/lib/http/retriable/errors.rb +35 -0
- data/lib/http/retriable/performer.rb +197 -0
- data/lib/http/session.rb +280 -0
- data/lib/http/timeout/global.rb +229 -0
- data/lib/http/timeout/null.rb +225 -0
- data/lib/http/timeout/per_operation.rb +197 -0
- data/lib/http/uri/normalizer.rb +82 -0
- data/lib/http/uri/parsing.rb +182 -0
- data/lib/http/uri.rb +376 -0
- data/lib/http/version.rb +6 -0
- data/lib/http.rb +36 -0
- data/sig/deps.rbs +122 -0
- data/sig/http.rbs +1619 -0
- data/test/http/base64_test.rb +28 -0
- data/test/http/client_test.rb +739 -0
- data/test/http/connection_test.rb +1533 -0
- data/test/http/content_type_test.rb +190 -0
- data/test/http/errors_test.rb +28 -0
- data/test/http/feature_test.rb +49 -0
- data/test/http/features/auto_deflate_test.rb +317 -0
- data/test/http/features/auto_inflate_test.rb +213 -0
- data/test/http/features/caching_test.rb +942 -0
- data/test/http/features/digest_auth_test.rb +996 -0
- data/test/http/features/instrumentation_test.rb +246 -0
- data/test/http/features/logging_test.rb +654 -0
- data/test/http/features/normalize_uri_test.rb +41 -0
- data/test/http/features/raise_error_test.rb +77 -0
- data/test/http/form_data/composite_io_test.rb +215 -0
- data/test/http/form_data/file_test.rb +255 -0
- data/test/http/form_data/fixtures/the-http-gem.info +1 -0
- data/test/http/form_data/multipart_test.rb +303 -0
- data/test/http/form_data/part_test.rb +90 -0
- data/test/http/form_data/urlencoded_test.rb +164 -0
- data/test/http/form_data_test.rb +232 -0
- data/test/http/headers/normalizer_test.rb +93 -0
- data/test/http/headers_test.rb +888 -0
- data/test/http/mime_type/json_test.rb +39 -0
- data/test/http/mime_type_test.rb +150 -0
- data/test/http/options/base_uri_test.rb +148 -0
- data/test/http/options/body_test.rb +21 -0
- data/test/http/options/features_test.rb +38 -0
- data/test/http/options/form_test.rb +21 -0
- data/test/http/options/headers_test.rb +32 -0
- data/test/http/options/json_test.rb +21 -0
- data/test/http/options/merge_test.rb +78 -0
- data/test/http/options/new_test.rb +37 -0
- data/test/http/options/proxy_test.rb +32 -0
- data/test/http/options_test.rb +575 -0
- data/test/http/redirector_test.rb +639 -0
- data/test/http/request/body_test.rb +318 -0
- data/test/http/request/builder_test.rb +623 -0
- data/test/http/request/writer_test.rb +391 -0
- data/test/http/request_test.rb +1733 -0
- data/test/http/response/body_test.rb +292 -0
- data/test/http/response/parser_test.rb +105 -0
- data/test/http/response/status_test.rb +322 -0
- data/test/http/response_test.rb +502 -0
- data/test/http/retriable/delay_calculator_test.rb +194 -0
- data/test/http/retriable/errors_test.rb +71 -0
- data/test/http/retriable/performer_test.rb +551 -0
- data/test/http/session_test.rb +424 -0
- data/test/http/timeout/global_test.rb +239 -0
- data/test/http/timeout/null_test.rb +218 -0
- data/test/http/timeout/per_operation_test.rb +220 -0
- data/test/http/uri/normalizer_test.rb +89 -0
- data/test/http/uri_test.rb +1140 -0
- data/test/http/version_test.rb +15 -0
- data/test/http_test.rb +818 -0
- data/test/regression_tests.rb +27 -0
- data/test/support/capture_warning.rb +10 -0
- data/test/support/dummy_server/encoding_routes.rb +47 -0
- data/test/support/dummy_server/routes.rb +201 -0
- data/test/support/dummy_server/servlet.rb +81 -0
- data/test/support/dummy_server.rb +200 -0
- data/test/support/fakeio.rb +21 -0
- data/test/support/http_handling_shared/connection_reuse_tests.rb +97 -0
- data/test/support/http_handling_shared/timeout_tests.rb +134 -0
- data/test/support/http_handling_shared.rb +11 -0
- data/test/support/proxy_server.rb +207 -0
- data/test/support/servers/runner.rb +67 -0
- data/test/support/simplecov.rb +28 -0
- data/test/support/ssl_helper.rb +108 -0
- data/test/test_helper.rb +38 -0
- metadata +218 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HTTP
|
|
4
|
+
module Chainable
|
|
5
|
+
# HTTP verb shortcut methods
|
|
6
|
+
#
|
|
7
|
+
# Each method delegates to {Chainable#request} with the appropriate verb.
|
|
8
|
+
module Verbs
|
|
9
|
+
# Request a get sans response body
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# HTTP.head("http://example.com")
|
|
13
|
+
#
|
|
14
|
+
# @param [String, URI] uri URI to request
|
|
15
|
+
# @param options [Hash] request options
|
|
16
|
+
# @yieldparam response [HTTP::Response] the response
|
|
17
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
18
|
+
# @api public
|
|
19
|
+
def head(uri, **, &)
|
|
20
|
+
request(:head, uri, **, &) # steep:ignore
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Get a resource
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# HTTP.get("http://example.com")
|
|
27
|
+
#
|
|
28
|
+
# @param [String, URI] uri URI to request
|
|
29
|
+
# @param options [Hash] request options
|
|
30
|
+
# @yieldparam response [HTTP::Response] the response
|
|
31
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
32
|
+
# @api public
|
|
33
|
+
def get(uri, **, &)
|
|
34
|
+
request(:get, uri, **, &) # steep:ignore
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Post to a resource
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# HTTP.post("http://example.com", body: "data")
|
|
41
|
+
#
|
|
42
|
+
# @param [String, URI] uri URI to request
|
|
43
|
+
# @param options [Hash] request options
|
|
44
|
+
# @yieldparam response [HTTP::Response] the response
|
|
45
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
46
|
+
# @api public
|
|
47
|
+
def post(uri, **, &)
|
|
48
|
+
request(:post, uri, **, &) # steep:ignore
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Put to a resource
|
|
52
|
+
#
|
|
53
|
+
# @example
|
|
54
|
+
# HTTP.put("http://example.com", body: "data")
|
|
55
|
+
#
|
|
56
|
+
# @param [String, URI] uri URI to request
|
|
57
|
+
# @param options [Hash] request options
|
|
58
|
+
# @yieldparam response [HTTP::Response] the response
|
|
59
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
60
|
+
# @api public
|
|
61
|
+
def put(uri, **, &)
|
|
62
|
+
request(:put, uri, **, &) # steep:ignore
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Delete a resource
|
|
66
|
+
#
|
|
67
|
+
# @example
|
|
68
|
+
# HTTP.delete("http://example.com/resource")
|
|
69
|
+
#
|
|
70
|
+
# @param [String, URI] uri URI to request
|
|
71
|
+
# @param options [Hash] request options
|
|
72
|
+
# @yieldparam response [HTTP::Response] the response
|
|
73
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
74
|
+
# @api public
|
|
75
|
+
def delete(uri, **, &)
|
|
76
|
+
request(:delete, uri, **, &) # steep:ignore
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Echo the request back to the client
|
|
80
|
+
#
|
|
81
|
+
# @example
|
|
82
|
+
# HTTP.trace("http://example.com")
|
|
83
|
+
#
|
|
84
|
+
# @param [String, URI] uri URI to request
|
|
85
|
+
# @param options [Hash] request options
|
|
86
|
+
# @yieldparam response [HTTP::Response] the response
|
|
87
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
88
|
+
# @api public
|
|
89
|
+
def trace(uri, **, &)
|
|
90
|
+
request(:trace, uri, **, &) # steep:ignore
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Return the methods supported on the given URI
|
|
94
|
+
#
|
|
95
|
+
# @example
|
|
96
|
+
# HTTP.options("http://example.com")
|
|
97
|
+
#
|
|
98
|
+
# @param [String, URI] uri URI to request
|
|
99
|
+
# @param options [Hash] request options
|
|
100
|
+
# @yieldparam response [HTTP::Response] the response
|
|
101
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
102
|
+
# @api public
|
|
103
|
+
def options(uri, **, &)
|
|
104
|
+
request(:options, uri, **, &) # steep:ignore
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Convert to a transparent TCP/IP tunnel
|
|
108
|
+
#
|
|
109
|
+
# @example
|
|
110
|
+
# HTTP.connect("http://example.com")
|
|
111
|
+
#
|
|
112
|
+
# @param [String, URI] uri URI to request
|
|
113
|
+
# @param options [Hash] request options
|
|
114
|
+
# @yieldparam response [HTTP::Response] the response
|
|
115
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
116
|
+
# @api public
|
|
117
|
+
def connect(uri, **, &)
|
|
118
|
+
request(:connect, uri, **, &) # steep:ignore
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Apply partial modifications to a resource
|
|
122
|
+
#
|
|
123
|
+
# @example
|
|
124
|
+
# HTTP.patch("http://example.com/resource", body: "data")
|
|
125
|
+
#
|
|
126
|
+
# @param [String, URI] uri URI to request
|
|
127
|
+
# @param options [Hash] request options
|
|
128
|
+
# @yieldparam response [HTTP::Response] the response
|
|
129
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
130
|
+
# @api public
|
|
131
|
+
def patch(uri, **, &)
|
|
132
|
+
request(:patch, uri, **, &) # steep:ignore
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "http/base64"
|
|
4
|
+
require "http/chainable/helpers"
|
|
5
|
+
require "http/chainable/verbs"
|
|
6
|
+
require "http/headers"
|
|
7
|
+
|
|
8
|
+
module HTTP
|
|
9
|
+
# HTTP verb methods and client configuration DSL
|
|
10
|
+
module Chainable
|
|
11
|
+
include HTTP::Base64
|
|
12
|
+
include Verbs
|
|
13
|
+
|
|
14
|
+
# Make an HTTP request with the given verb
|
|
15
|
+
#
|
|
16
|
+
# @example Without a block
|
|
17
|
+
# HTTP.request(:get, "http://example.com")
|
|
18
|
+
#
|
|
19
|
+
# @example With a block (auto-closes connection)
|
|
20
|
+
# HTTP.request(:get, "http://example.com") { |res| res.status }
|
|
21
|
+
#
|
|
22
|
+
# @param (see Client#request)
|
|
23
|
+
# @yieldparam response [HTTP::Response] the response
|
|
24
|
+
# @return [HTTP::Response, Object] the response, or block return value
|
|
25
|
+
# @api public
|
|
26
|
+
def request(verb, uri, **, &block)
|
|
27
|
+
client = make_client(default_options)
|
|
28
|
+
response = client.request(verb, uri, **)
|
|
29
|
+
return response unless block
|
|
30
|
+
|
|
31
|
+
yield response
|
|
32
|
+
ensure
|
|
33
|
+
client&.close if block
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Set timeout on the request
|
|
37
|
+
#
|
|
38
|
+
# @example
|
|
39
|
+
# HTTP.timeout(10).get("http://example.com")
|
|
40
|
+
#
|
|
41
|
+
# @overload timeout(options = {})
|
|
42
|
+
# Adds per operation timeouts to the request
|
|
43
|
+
# @param [Hash] options
|
|
44
|
+
# @option options [Float] :read Read timeout
|
|
45
|
+
# @option options [Float] :write Write timeout
|
|
46
|
+
# @option options [Float] :connect Connect timeout
|
|
47
|
+
# @option options [Float] :global Global timeout (combines with per-operation)
|
|
48
|
+
# @overload timeout(global_timeout)
|
|
49
|
+
# Adds a global timeout to the full request
|
|
50
|
+
# @param [Numeric] global_timeout
|
|
51
|
+
# @return [HTTP::Session]
|
|
52
|
+
# @api public
|
|
53
|
+
def timeout(options)
|
|
54
|
+
klass, options = case options
|
|
55
|
+
when Numeric then [HTTP::Timeout::Global, { global_timeout: options }]
|
|
56
|
+
when Hash then resolve_timeout_hash(options)
|
|
57
|
+
when :null then [HTTP::Timeout::Null, {}]
|
|
58
|
+
else raise ArgumentError,
|
|
59
|
+
"Use `.timeout(:null)`, " \
|
|
60
|
+
"`.timeout(global_timeout_in_seconds)` or " \
|
|
61
|
+
"`.timeout(connect: x, write: y, read: z)`."
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
branch default_options.merge(
|
|
65
|
+
timeout_class: klass,
|
|
66
|
+
timeout_options: options
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Set a base URI for resolving relative request paths
|
|
71
|
+
#
|
|
72
|
+
# The first call must use an absolute URI that includes a scheme
|
|
73
|
+
# (e.g. "https://example.com"). Once a base URI is set, subsequent chained
|
|
74
|
+
# calls may use relative paths that are resolved against the existing base.
|
|
75
|
+
#
|
|
76
|
+
# @example
|
|
77
|
+
# HTTP.base_uri("https://example.com/api/v1").get("users")
|
|
78
|
+
#
|
|
79
|
+
# @example Chaining base URIs
|
|
80
|
+
# HTTP.base_uri("https://example.com").base_uri("api/v1").get("users")
|
|
81
|
+
#
|
|
82
|
+
# @param [String, HTTP::URI] uri the base URI (absolute with scheme when
|
|
83
|
+
# no base is set; may be relative when chaining)
|
|
84
|
+
# @return [HTTP::Session]
|
|
85
|
+
# @raise [HTTP::Error] if no base URI is set and the given URI has no scheme
|
|
86
|
+
# @api public
|
|
87
|
+
def base_uri(uri)
|
|
88
|
+
branch default_options.with_base_uri(uri)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Open a persistent connection to a host
|
|
92
|
+
#
|
|
93
|
+
# Returns an {HTTP::Session} that pools persistent {HTTP::Client}
|
|
94
|
+
# instances by origin. This allows connection reuse within the same
|
|
95
|
+
# origin and transparent cross-origin redirect handling.
|
|
96
|
+
#
|
|
97
|
+
# When no host is given, the origin is derived from the configured base URI.
|
|
98
|
+
#
|
|
99
|
+
# @example
|
|
100
|
+
# HTTP.persistent("http://example.com").get("/")
|
|
101
|
+
#
|
|
102
|
+
# @example Derive host from base URI
|
|
103
|
+
# HTTP.base_uri("https://example.com/api").persistent.get("users")
|
|
104
|
+
#
|
|
105
|
+
# @overload persistent(host = nil, timeout: 5)
|
|
106
|
+
# Flags as persistent
|
|
107
|
+
# @param [String, nil] host connection origin (derived from base URI when nil)
|
|
108
|
+
# @option [Integer] timeout Keep alive timeout
|
|
109
|
+
# @raise [ArgumentError] if host is nil and no base URI is set
|
|
110
|
+
# @raise [Request::Error] if Host is invalid
|
|
111
|
+
# @return [HTTP::Session] Persistent session
|
|
112
|
+
# @overload persistent(host = nil, timeout: 5, &block)
|
|
113
|
+
# Executes given block with persistent session and automatically closes
|
|
114
|
+
# all connections at the end of execution.
|
|
115
|
+
#
|
|
116
|
+
# @example
|
|
117
|
+
#
|
|
118
|
+
# def keys(users)
|
|
119
|
+
# HTTP.persistent("https://github.com") do |http|
|
|
120
|
+
# users.map { |u| http.get("/#{u}.keys").to_s }
|
|
121
|
+
# end
|
|
122
|
+
# end
|
|
123
|
+
#
|
|
124
|
+
# # same as
|
|
125
|
+
#
|
|
126
|
+
# def keys(users)
|
|
127
|
+
# http = HTTP.persistent "https://github.com"
|
|
128
|
+
# users.map { |u| http.get("/#{u}.keys").to_s }
|
|
129
|
+
# ensure
|
|
130
|
+
# http.close if http
|
|
131
|
+
# end
|
|
132
|
+
#
|
|
133
|
+
#
|
|
134
|
+
# @yieldparam [HTTP::Session] session Persistent session
|
|
135
|
+
# @return [Object] result of last expression in the block
|
|
136
|
+
# @return [HTTP::Session, Object]
|
|
137
|
+
# @api public
|
|
138
|
+
def persistent(host = nil, timeout: 5)
|
|
139
|
+
host ||= default_options.base_uri&.origin
|
|
140
|
+
raise ArgumentError, "host is required for persistent connections" unless host
|
|
141
|
+
|
|
142
|
+
options = default_options.merge(keep_alive_timeout: timeout).with_persistent(host)
|
|
143
|
+
session = branch(options)
|
|
144
|
+
return session unless block_given?
|
|
145
|
+
|
|
146
|
+
yield session
|
|
147
|
+
ensure
|
|
148
|
+
session&.close if block_given?
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Make a request through an HTTP proxy
|
|
152
|
+
#
|
|
153
|
+
# @example
|
|
154
|
+
# HTTP.via("proxy.example.com", 8080).get("http://example.com")
|
|
155
|
+
#
|
|
156
|
+
# @param [Array] proxy
|
|
157
|
+
# @raise [Request::Error] if HTTP proxy is invalid
|
|
158
|
+
# @return [HTTP::Session]
|
|
159
|
+
# @api public
|
|
160
|
+
def via(*proxy)
|
|
161
|
+
proxy_hash = build_proxy_hash(proxy)
|
|
162
|
+
|
|
163
|
+
raise(RequestError, "invalid HTTP proxy: #{proxy_hash}") unless (2..5).cover?(proxy_hash.keys.size)
|
|
164
|
+
|
|
165
|
+
branch default_options.with_proxy(proxy_hash)
|
|
166
|
+
end
|
|
167
|
+
alias through via
|
|
168
|
+
|
|
169
|
+
# Make client follow redirects
|
|
170
|
+
#
|
|
171
|
+
# @example
|
|
172
|
+
# HTTP.follow.get("http://example.com")
|
|
173
|
+
#
|
|
174
|
+
# @param [Boolean] strict (true) redirector hops policy
|
|
175
|
+
# @param [Integer] max_hops (5) maximum allowed redirect hops
|
|
176
|
+
# @param [#call, nil] on_redirect optional redirect callback
|
|
177
|
+
# @return [HTTP::Session]
|
|
178
|
+
# @see Redirector#initialize
|
|
179
|
+
# @api public
|
|
180
|
+
def follow(strict: nil, max_hops: nil, on_redirect: nil)
|
|
181
|
+
opts = { strict: strict, max_hops: max_hops, on_redirect: on_redirect }.compact
|
|
182
|
+
branch default_options.with_follow(opts)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Make a request with the given headers
|
|
186
|
+
#
|
|
187
|
+
# @example
|
|
188
|
+
# HTTP.headers("Accept" => "text/plain").get("http://example.com")
|
|
189
|
+
#
|
|
190
|
+
# @param [Hash] headers request headers
|
|
191
|
+
# @return [HTTP::Session]
|
|
192
|
+
# @api public
|
|
193
|
+
def headers(headers)
|
|
194
|
+
branch default_options.with_headers(headers)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Make a request with the given cookies
|
|
198
|
+
#
|
|
199
|
+
# @example
|
|
200
|
+
# HTTP.cookies(session: "abc123").get("http://example.com")
|
|
201
|
+
#
|
|
202
|
+
# @param [Hash, Array<HTTP::Cookie>] cookies cookies to set
|
|
203
|
+
# @return [HTTP::Session]
|
|
204
|
+
# @api public
|
|
205
|
+
def cookies(cookies)
|
|
206
|
+
value = cookies.map do |entry|
|
|
207
|
+
case entry
|
|
208
|
+
when HTTP::Cookie then entry.cookie_value
|
|
209
|
+
else
|
|
210
|
+
name, val = entry
|
|
211
|
+
HTTP::Cookie.new(name.to_s, val.to_s).cookie_value
|
|
212
|
+
end
|
|
213
|
+
end.join("; ")
|
|
214
|
+
|
|
215
|
+
headers(Headers::COOKIE => value)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Force a specific encoding for response body
|
|
219
|
+
#
|
|
220
|
+
# @example
|
|
221
|
+
# HTTP.encoding("UTF-8").get("http://example.com")
|
|
222
|
+
#
|
|
223
|
+
# @param [String, Encoding] encoding encoding to use
|
|
224
|
+
# @return [HTTP::Session]
|
|
225
|
+
# @api public
|
|
226
|
+
def encoding(encoding)
|
|
227
|
+
branch default_options.with_encoding(encoding)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Accept the given MIME type(s)
|
|
231
|
+
#
|
|
232
|
+
# @example
|
|
233
|
+
# HTTP.accept("application/json").get("http://example.com")
|
|
234
|
+
#
|
|
235
|
+
# @param [String, Symbol] type MIME type to accept
|
|
236
|
+
# @return [HTTP::Session]
|
|
237
|
+
# @api public
|
|
238
|
+
def accept(type)
|
|
239
|
+
headers Headers::ACCEPT => MimeType.normalize(type)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Make a request with the given Authorization header
|
|
243
|
+
#
|
|
244
|
+
# @example
|
|
245
|
+
# HTTP.auth("Bearer token123").get("http://example.com")
|
|
246
|
+
#
|
|
247
|
+
# @param [#to_s] value Authorization header value
|
|
248
|
+
# @return [HTTP::Session]
|
|
249
|
+
# @api public
|
|
250
|
+
def auth(value)
|
|
251
|
+
headers Headers::AUTHORIZATION => value.to_s
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Make a request with the given Basic authorization header
|
|
255
|
+
#
|
|
256
|
+
# @example
|
|
257
|
+
# HTTP.basic_auth(user: "user", pass: "pass").get("http://example.com")
|
|
258
|
+
#
|
|
259
|
+
# @see http://tools.ietf.org/html/rfc2617
|
|
260
|
+
# @param [#to_s] user
|
|
261
|
+
# @param [#to_s] pass
|
|
262
|
+
# @return [HTTP::Session]
|
|
263
|
+
# @api public
|
|
264
|
+
def basic_auth(user:, pass:)
|
|
265
|
+
auth("Basic #{encode64("#{user}:#{pass}")}")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Enable HTTP Digest authentication
|
|
269
|
+
#
|
|
270
|
+
# Automatically handles 401 Digest challenges by computing the digest
|
|
271
|
+
# response and retrying the request with proper credentials.
|
|
272
|
+
#
|
|
273
|
+
# @example
|
|
274
|
+
# HTTP.digest_auth(user: "admin", pass: "secret").get("http://example.com")
|
|
275
|
+
#
|
|
276
|
+
# @see https://datatracker.ietf.org/doc/html/rfc2617
|
|
277
|
+
# @param [#to_s] user
|
|
278
|
+
# @param [#to_s] pass
|
|
279
|
+
# @return [HTTP::Session]
|
|
280
|
+
# @api public
|
|
281
|
+
def digest_auth(user:, pass:)
|
|
282
|
+
use(digest_auth: { user: user, pass: pass })
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Get options for HTTP
|
|
286
|
+
#
|
|
287
|
+
# @example
|
|
288
|
+
# HTTP.default_options
|
|
289
|
+
#
|
|
290
|
+
# @return [HTTP::Options]
|
|
291
|
+
# @api public
|
|
292
|
+
def default_options
|
|
293
|
+
@default_options ||= HTTP::Options.new
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Set options for HTTP
|
|
297
|
+
#
|
|
298
|
+
# @example
|
|
299
|
+
# HTTP.default_options = { response: :object }
|
|
300
|
+
#
|
|
301
|
+
# @param [Hash, HTTP::Options] opts options to set
|
|
302
|
+
# @return [HTTP::Options]
|
|
303
|
+
# @api public
|
|
304
|
+
def default_options=(opts)
|
|
305
|
+
@default_options = HTTP::Options.new(opts)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Set TCP_NODELAY on the socket
|
|
309
|
+
#
|
|
310
|
+
# @example
|
|
311
|
+
# HTTP.nodelay.get("http://example.com")
|
|
312
|
+
#
|
|
313
|
+
# @return [HTTP::Session]
|
|
314
|
+
# @api public
|
|
315
|
+
def nodelay
|
|
316
|
+
branch default_options.with_nodelay(true)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Enable one or more features
|
|
320
|
+
#
|
|
321
|
+
# @example
|
|
322
|
+
# HTTP.use(:auto_inflate).get("http://example.com")
|
|
323
|
+
#
|
|
324
|
+
# @param [Array<Symbol, Hash>] features features to enable
|
|
325
|
+
# @return [HTTP::Session]
|
|
326
|
+
# @api public
|
|
327
|
+
def use(*features)
|
|
328
|
+
branch default_options.with_features(features)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Return a retriable session that retries on failure
|
|
332
|
+
#
|
|
333
|
+
# @example Usage
|
|
334
|
+
#
|
|
335
|
+
# # Retry max 5 times with randomly growing delay between retries
|
|
336
|
+
# HTTP.retriable.get(url)
|
|
337
|
+
#
|
|
338
|
+
# # Retry max 3 times with randomly growing delay between retries
|
|
339
|
+
# HTTP.retriable(tries: 3).get(url)
|
|
340
|
+
#
|
|
341
|
+
# # Retry max 3 times with 1 sec delay between retries
|
|
342
|
+
# HTTP.retriable(tries: 3, delay: proc { 1 }).get(url)
|
|
343
|
+
#
|
|
344
|
+
# # Retry max 3 times with geometrically progressed delay between retries
|
|
345
|
+
# HTTP.retriable(tries: 3, delay: proc { |i| 1 + i*i }).get(url)
|
|
346
|
+
#
|
|
347
|
+
# @param (see Performer#initialize)
|
|
348
|
+
# @return [HTTP::Session]
|
|
349
|
+
# @api public
|
|
350
|
+
def retriable(tries: nil, delay: nil, exceptions: nil, retry_statuses: nil,
|
|
351
|
+
on_retry: nil, max_delay: nil, should_retry: nil)
|
|
352
|
+
opts = { tries: tries, delay: delay, exceptions: exceptions, retry_statuses: retry_statuses,
|
|
353
|
+
on_retry: on_retry, max_delay: max_delay, should_retry: should_retry }.compact
|
|
354
|
+
branch default_options.with_retriable(opts.empty? || opts)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
private
|
|
358
|
+
|
|
359
|
+
# Create a new session with the given options
|
|
360
|
+
#
|
|
361
|
+
# @param [HTTP::Options] options options for the session
|
|
362
|
+
# @return [HTTP::Session]
|
|
363
|
+
# @api private
|
|
364
|
+
def branch(options)
|
|
365
|
+
HTTP::Session.new(options)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# Create a new client for executing a request
|
|
369
|
+
#
|
|
370
|
+
# @param [HTTP::Options] options options for the client
|
|
371
|
+
# @return [HTTP::Client]
|
|
372
|
+
# @api private
|
|
373
|
+
def make_client(options)
|
|
374
|
+
HTTP::Client.new(options)
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|