faraday 0.12.2 → 1.3.0
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 +5 -5
- data/CHANGELOG.md +350 -0
- data/LICENSE.md +1 -1
- data/README.md +22 -325
- data/Rakefile +7 -0
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday.rb +120 -188
- data/lib/faraday/adapter.rb +84 -22
- data/lib/faraday/adapter/em_http.rb +150 -104
- data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
- data/lib/faraday/adapter/em_synchrony.rb +110 -63
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
- data/lib/faraday/adapter/excon.rb +98 -54
- data/lib/faraday/adapter/httpclient.rb +83 -59
- data/lib/faraday/adapter/net_http_persistent.rb +68 -27
- data/lib/faraday/adapter/patron.rb +86 -37
- data/lib/faraday/adapter/rack.rb +30 -13
- data/lib/faraday/adapter/test.rb +103 -62
- data/lib/faraday/adapter/typhoeus.rb +7 -115
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +46 -36
- data/lib/faraday/connection.rb +336 -177
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +126 -37
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/methods.rb +6 -0
- data/lib/faraday/middleware.rb +19 -25
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options.rb +39 -193
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +28 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -196
- data/lib/faraday/rack_builder.rb +77 -63
- data/lib/faraday/request.rb +94 -32
- data/lib/faraday/request/authorization.rb +44 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/multipart.rb +86 -48
- data/lib/faraday/request/retry.rb +209 -134
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/response.rb +27 -23
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +49 -14
- data/lib/faraday/utils.rb +38 -247
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/version.rb +5 -0
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +47 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
- data/spec/faraday/adapter/excon_spec.rb +49 -0
- data/spec/faraday/adapter/httpclient_spec.rb +73 -0
- data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
- data/spec/faraday/adapter/net_http_spec.rb +64 -0
- data/spec/faraday/adapter/patron_spec.rb +18 -0
- data/spec/faraday/adapter/rack_spec.rb +8 -0
- data/spec/faraday/adapter/test_spec.rb +260 -0
- data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/composite_read_io_spec.rb +80 -0
- data/spec/faraday/connection_spec.rb +691 -0
- data/spec/faraday/error_spec.rb +60 -0
- data/spec/faraday/middleware_spec.rb +52 -0
- data/spec/faraday/options/env_spec.rb +70 -0
- data/spec/faraday/options/options_spec.rb +297 -0
- data/spec/faraday/options/proxy_options_spec.rb +37 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +345 -0
- data/spec/faraday/request/authorization_spec.rb +88 -0
- data/spec/faraday/request/instrumentation_spec.rb +76 -0
- data/spec/faraday/request/multipart_spec.rb +302 -0
- data/spec/faraday/request/retry_spec.rb +242 -0
- data/spec/faraday/request/url_encoded_spec.rb +83 -0
- data/spec/faraday/request_spec.rb +120 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/middleware_spec.rb +68 -0
- data/spec/faraday/response/raise_error_spec.rb +169 -0
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +56 -0
- data/spec/faraday_spec.rb +37 -0
- data/spec/spec_helper.rb +132 -0
- data/spec/support/disabling_stub.rb +14 -0
- data/spec/support/fake_safe_buffer.rb +15 -0
- data/spec/support/helper_methods.rb +133 -0
- data/spec/support/shared_examples/adapter.rb +105 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +262 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +109 -10
- data/lib/faraday/adapter/net_http.rb +0 -135
- data/lib/faraday/upload_io.rb +0 -67
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'monitor'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
# AdapterRegistry registers adapter class names so they can be looked up by a
|
7
|
+
# String or Symbol name.
|
8
|
+
class AdapterRegistry
|
9
|
+
def initialize
|
10
|
+
@lock = Monitor.new
|
11
|
+
@constants = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(name)
|
15
|
+
klass = @lock.synchronize do
|
16
|
+
@constants[name]
|
17
|
+
end
|
18
|
+
return klass if klass
|
19
|
+
|
20
|
+
Object.const_get(name).tap { |c| set(c, name) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def set(klass, name = nil)
|
24
|
+
name ||= klass.to_s
|
25
|
+
@lock.synchronize do
|
26
|
+
@constants[name] = klass
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/faraday/autoload.rb
CHANGED
@@ -1,84 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
#
|
4
|
+
# Adds the ability for other modules to manage autoloadable
|
3
5
|
# constants.
|
6
|
+
#
|
7
|
+
# @api private
|
4
8
|
module AutoloadHelper
|
5
|
-
#
|
9
|
+
# Registers the constants to be auto loaded.
|
6
10
|
#
|
7
|
-
# prefix
|
8
|
-
# it will be prefixed with the root path of this loaded
|
9
|
-
# version.
|
10
|
-
# options
|
11
|
+
# @param prefix [String] The require prefix. If the path is inside Faraday,
|
12
|
+
# then it will be prefixed with the root path of this loaded
|
13
|
+
# Faraday version.
|
14
|
+
# @param options [{ Symbol => String }] library names.
|
11
15
|
#
|
12
|
-
#
|
16
|
+
# @example
|
13
17
|
#
|
14
18
|
# Faraday.autoload_all 'faraday/foo',
|
15
|
-
# :
|
19
|
+
# Bar: 'bar'
|
16
20
|
#
|
17
21
|
# # requires faraday/foo/bar to load Faraday::Bar.
|
18
22
|
# Faraday::Bar
|
19
23
|
#
|
20
|
-
#
|
21
|
-
# Returns nothing.
|
24
|
+
# @return [void]
|
22
25
|
def autoload_all(prefix, options)
|
23
|
-
if prefix
|
26
|
+
if prefix.match? %r{^faraday(/|$)}i
|
24
27
|
prefix = File.join(Faraday.root_path, prefix)
|
25
28
|
end
|
29
|
+
|
26
30
|
options.each do |const_name, path|
|
27
31
|
autoload const_name, File.join(prefix, path)
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
|
-
#
|
35
|
+
# Loads each autoloaded constant. If thread safety is a concern,
|
32
36
|
# wrap this in a Mutex.
|
33
37
|
#
|
34
|
-
#
|
38
|
+
# @return [void]
|
35
39
|
def load_autoloaded_constants
|
36
40
|
constants.each do |const|
|
37
41
|
const_get(const) if autoload?(const)
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
41
|
-
#
|
45
|
+
# Filters the module's contents with those that have been already
|
42
46
|
# autoloaded.
|
43
47
|
#
|
44
|
-
#
|
48
|
+
# @return [Array<Class, Module>]
|
45
49
|
def all_loaded_constants
|
46
|
-
constants
|
47
|
-
|
50
|
+
constants
|
51
|
+
.map { |c| const_get(c) }
|
52
|
+
.select { |a| a.respond_to?(:loaded?) && a.loaded? }
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
56
|
+
# Adapter is the base class for all Faraday adapters.
|
57
|
+
# @see lib/faraday/adapter.rb Original class location
|
51
58
|
class Adapter
|
52
59
|
extend AutoloadHelper
|
53
60
|
autoload_all 'faraday/adapter',
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
:HTTPClient => 'httpclient'
|
61
|
+
NetHttpPersistent: 'net_http_persistent',
|
62
|
+
EMSynchrony: 'em_synchrony',
|
63
|
+
EMHttp: 'em_http',
|
64
|
+
Typhoeus: 'typhoeus',
|
65
|
+
Patron: 'patron',
|
66
|
+
Excon: 'excon',
|
67
|
+
Test: 'test',
|
68
|
+
Rack: 'rack',
|
69
|
+
HTTPClient: 'httpclient'
|
64
70
|
end
|
65
71
|
|
72
|
+
# Request represents a single HTTP request for a Faraday adapter to make.
|
73
|
+
# @see lib/faraday/request.rb Original class location
|
66
74
|
class Request
|
67
75
|
extend AutoloadHelper
|
68
76
|
autoload_all 'faraday/request',
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
77
|
+
UrlEncoded: 'url_encoded',
|
78
|
+
Multipart: 'multipart',
|
79
|
+
Retry: 'retry',
|
80
|
+
Authorization: 'authorization',
|
81
|
+
BasicAuthentication: 'basic_authentication',
|
82
|
+
TokenAuthentication: 'token_authentication',
|
83
|
+
Instrumentation: 'instrumentation'
|
76
84
|
end
|
77
85
|
|
86
|
+
# Response represents the returned value of a sent Faraday request.
|
87
|
+
# @see lib/faraday/response.rb Original class location
|
78
88
|
class Response
|
79
89
|
extend AutoloadHelper
|
80
90
|
autoload_all 'faraday/response',
|
81
|
-
|
82
|
-
|
91
|
+
RaiseError: 'raise_error',
|
92
|
+
Logger: 'logger'
|
83
93
|
end
|
84
94
|
end
|
data/lib/faraday/connection.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
#
|
4
|
+
# Connection objects manage the default properties and the middleware
|
3
5
|
# stack for fulfilling an HTTP request.
|
4
6
|
#
|
5
|
-
#
|
7
|
+
# @example
|
6
8
|
#
|
7
9
|
# conn = Faraday::Connection.new 'http://sushi.com'
|
8
10
|
#
|
@@ -12,48 +14,51 @@ module Faraday
|
|
12
14
|
#
|
13
15
|
class Connection
|
14
16
|
# A Set of allowed HTTP verbs.
|
15
|
-
METHODS = Set.new [
|
17
|
+
METHODS = Set.new %i[get post put delete head patch options trace]
|
16
18
|
|
17
|
-
#
|
19
|
+
# @return [Hash] URI query unencoded key/value pairs.
|
18
20
|
attr_reader :params
|
19
21
|
|
20
|
-
#
|
22
|
+
# @return [Hash] unencoded HTTP header key/value pairs.
|
21
23
|
attr_reader :headers
|
22
24
|
|
23
|
-
#
|
24
|
-
#
|
25
|
+
# @return [String] a URI with the prefix used for all requests from this
|
26
|
+
# Connection. This includes a default host name, scheme, port, and path.
|
25
27
|
attr_reader :url_prefix
|
26
28
|
|
27
|
-
#
|
29
|
+
# @return [Faraday::Builder] Builder for this Connection.
|
28
30
|
attr_reader :builder
|
29
31
|
|
30
|
-
#
|
31
|
-
attr_reader :options
|
32
|
-
|
33
|
-
# Public: Returns a Hash of the SSL options.
|
32
|
+
# @return [Hash] SSL options.
|
34
33
|
attr_reader :ssl
|
35
34
|
|
36
|
-
#
|
35
|
+
# @return [Object] the parallel manager for this Connection.
|
37
36
|
attr_reader :parallel_manager
|
38
37
|
|
39
|
-
#
|
38
|
+
# Sets the default parallel manager for this connection.
|
40
39
|
attr_writer :default_parallel_manager
|
41
40
|
|
42
|
-
#
|
41
|
+
# @return [Hash] proxy options.
|
42
|
+
attr_reader :proxy
|
43
|
+
|
44
|
+
# Initializes a new Faraday::Connection.
|
43
45
|
#
|
44
|
-
# url
|
46
|
+
# @param url [URI, String] URI or String base URL to use as a prefix for all
|
45
47
|
# requests (optional).
|
46
|
-
# options
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
48
|
+
# @param options [Hash, Faraday::ConnectionOptions]
|
49
|
+
# @option options [URI, String] :url ('http:/') URI or String base URL
|
50
|
+
# @option options [Hash<String => String>] :params URI query unencoded
|
51
|
+
# key/value pairs.
|
52
|
+
# @option options [Hash<String => String>] :headers Hash of unencoded HTTP
|
53
|
+
# header key/value pairs.
|
54
|
+
# @option options [Hash] :request Hash of request options.
|
55
|
+
# @option options [Hash] :ssl Hash of SSL options.
|
56
|
+
# @option options [Hash, URI, String] :proxy proxy options, either as a URL
|
57
|
+
# or as a Hash
|
58
|
+
# @option options [URI, String] :proxy[:uri]
|
59
|
+
# @option options [String] :proxy[:user]
|
60
|
+
# @option options [String] :proxy[:password]
|
61
|
+
# @yield [self] after all setup has been done
|
57
62
|
def initialize(url = nil, options = nil)
|
58
63
|
options = ConnectionOptions.from(options)
|
59
64
|
|
@@ -71,7 +76,7 @@ module Faraday
|
|
71
76
|
|
72
77
|
@builder = options.builder || begin
|
73
78
|
# pass an empty block to Builder so it doesn't assume default middleware
|
74
|
-
options.new_builder(block_given? ?
|
79
|
+
options.new_builder(block_given? ? proc { |b| } : nil)
|
75
80
|
end
|
76
81
|
|
77
82
|
self.url_prefix = url || 'http:/'
|
@@ -79,35 +84,31 @@ module Faraday
|
|
79
84
|
@params.update(options.params) if options.params
|
80
85
|
@headers.update(options.headers) if options.headers
|
81
86
|
|
82
|
-
|
83
|
-
proxy(options.fetch(:proxy) {
|
84
|
-
uri = nil
|
85
|
-
if URI.parse("").respond_to?(:find_proxy)
|
86
|
-
case url
|
87
|
-
when String
|
88
|
-
uri = URI.parse(url).find_proxy
|
89
|
-
when URI
|
90
|
-
uri = url.find_proxy
|
91
|
-
when nil
|
92
|
-
uri = find_default_proxy
|
93
|
-
end
|
94
|
-
else
|
95
|
-
uri = find_default_proxy
|
96
|
-
end
|
97
|
-
uri
|
98
|
-
})
|
87
|
+
initialize_proxy(url, options)
|
99
88
|
|
100
89
|
yield(self) if block_given?
|
101
90
|
|
102
91
|
@headers[:user_agent] ||= "Faraday v#{VERSION}"
|
103
92
|
end
|
104
93
|
|
105
|
-
|
94
|
+
def initialize_proxy(url, options)
|
95
|
+
@manual_proxy = !!options.proxy
|
96
|
+
@proxy =
|
97
|
+
if options.proxy
|
98
|
+
ProxyOptions.from(options.proxy)
|
99
|
+
else
|
100
|
+
proxy_from_env(url)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Sets the Hash of URI query unencoded key/value pairs.
|
105
|
+
# @param hash [Hash]
|
106
106
|
def params=(hash)
|
107
107
|
@params.replace hash
|
108
108
|
end
|
109
109
|
|
110
|
-
#
|
110
|
+
# Sets the Hash of unencoded HTTP header key/value pairs.
|
111
|
+
# @param hash [Hash]
|
111
112
|
def headers=(hash)
|
112
113
|
@headers.replace hash
|
113
114
|
end
|
@@ -116,71 +117,163 @@ module Faraday
|
|
116
117
|
|
117
118
|
def_delegators :builder, :build, :use, :request, :response, :adapter, :app
|
118
119
|
|
119
|
-
#
|
120
|
+
# Closes the underlying resources and/or connections. In the case of
|
121
|
+
# persistent connections, this closes all currently open connections
|
122
|
+
# but does not prevent new connections from being made.
|
123
|
+
def close
|
124
|
+
app.close
|
125
|
+
end
|
126
|
+
|
127
|
+
# @!method get(url = nil, params = nil, headers = nil)
|
128
|
+
# Makes a GET HTTP request without a body.
|
129
|
+
# @!scope class
|
120
130
|
#
|
121
|
-
# url
|
122
|
-
#
|
123
|
-
# params
|
124
|
-
# headers
|
131
|
+
# @param url [String] The optional String base URL to use as a prefix for
|
132
|
+
# all requests. Can also be the options Hash.
|
133
|
+
# @param params [Hash] Hash of URI query unencoded key/value pairs.
|
134
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
125
135
|
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
# conn.get '/items', {:page => 1}, :accept => 'application/json'
|
129
|
-
# conn.head '/items/1'
|
136
|
+
# @example
|
137
|
+
# conn.get '/items', { page: 1 }, :accept => 'application/json'
|
130
138
|
#
|
131
139
|
# # ElasticSearch example sending a body with GET.
|
132
140
|
# conn.get '/twitter/tweet/_search' do |req|
|
133
141
|
# req.headers[:content_type] = 'application/json'
|
134
142
|
# req.params[:routing] = 'kimchy'
|
135
|
-
# req.body = JSON.generate(:
|
143
|
+
# req.body = JSON.generate(query: {...})
|
136
144
|
# end
|
137
145
|
#
|
138
|
-
#
|
139
|
-
#
|
146
|
+
# @yield [Faraday::Request] for further request customizations
|
147
|
+
# @return [Faraday::Response]
|
148
|
+
|
149
|
+
# @!method head(url = nil, params = nil, headers = nil)
|
150
|
+
# Makes a HEAD HTTP request without a body.
|
151
|
+
# @!scope class
|
152
|
+
#
|
153
|
+
# @param url [String] The optional String base URL to use as a prefix for
|
154
|
+
# all requests. Can also be the options Hash.
|
155
|
+
# @param params [Hash] Hash of URI query unencoded key/value pairs.
|
156
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
157
|
+
#
|
158
|
+
# @example
|
159
|
+
# conn.head '/items/1'
|
160
|
+
#
|
161
|
+
# @yield [Faraday::Request] for further request customizations
|
162
|
+
# @return [Faraday::Response]
|
163
|
+
|
164
|
+
# @!method delete(url = nil, params = nil, headers = nil)
|
165
|
+
# Makes a DELETE HTTP request without a body.
|
166
|
+
# @!scope class
|
140
167
|
#
|
141
|
-
#
|
168
|
+
# @param url [String] The optional String base URL to use as a prefix for
|
169
|
+
# all requests. Can also be the options Hash.
|
170
|
+
# @param params [Hash] Hash of URI query unencoded key/value pairs.
|
171
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
142
172
|
#
|
143
|
-
#
|
173
|
+
# @example
|
174
|
+
# conn.delete '/items/1'
|
175
|
+
#
|
176
|
+
# @yield [Faraday::Request] for further request customizations
|
177
|
+
# @return [Faraday::Response]
|
178
|
+
|
179
|
+
# @!method trace(url = nil, params = nil, headers = nil)
|
180
|
+
# Makes a TRACE HTTP request without a body.
|
181
|
+
# @!scope class
|
144
182
|
#
|
145
|
-
#
|
146
|
-
|
183
|
+
# @param url [String] The optional String base URL to use as a prefix for
|
184
|
+
# all requests. Can also be the options Hash.
|
185
|
+
# @param params [Hash] Hash of URI query unencoded key/value pairs.
|
186
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
187
|
+
#
|
188
|
+
# @example
|
189
|
+
# conn.connect '/items/1'
|
190
|
+
#
|
191
|
+
# @yield [Faraday::Request] for further request customizations
|
192
|
+
# @return [Faraday::Response]
|
193
|
+
|
194
|
+
# @!visibility private
|
195
|
+
METHODS_WITH_QUERY.each do |method|
|
147
196
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
148
197
|
def #{method}(url = nil, params = nil, headers = nil)
|
149
|
-
run_request(:#{method}, url, nil, headers)
|
198
|
+
run_request(:#{method}, url, nil, headers) do |request|
|
150
199
|
request.params.update(params) if params
|
151
|
-
yield
|
152
|
-
|
200
|
+
yield request if block_given?
|
201
|
+
end
|
153
202
|
end
|
154
203
|
RUBY
|
155
204
|
end
|
156
205
|
|
157
|
-
#
|
206
|
+
# @overload options()
|
207
|
+
# Returns current Connection options.
|
158
208
|
#
|
159
|
-
# url
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
209
|
+
# @overload options(url, params = nil, headers = nil)
|
210
|
+
# Makes an OPTIONS HTTP request to the given URL.
|
211
|
+
# @param url [String] String base URL to sue as a prefix for all requests.
|
212
|
+
# @param params [Hash] Hash of URI query unencoded key/value pairs.
|
213
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
163
214
|
#
|
164
|
-
#
|
215
|
+
# @example
|
216
|
+
# conn.options '/items/1'
|
165
217
|
#
|
166
|
-
#
|
218
|
+
# @yield [Faraday::Request] for further request customizations
|
219
|
+
# @return [Faraday::Response]
|
220
|
+
def options(*args)
|
221
|
+
return @options if args.size.zero?
|
222
|
+
|
223
|
+
url, params, headers = *args
|
224
|
+
run_request(:options, url, nil, headers) do |request|
|
225
|
+
request.params.update(params) if params
|
226
|
+
yield request if block_given?
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# @!method post(url = nil, body = nil, headers = nil)
|
231
|
+
# Makes a POST HTTP request with a body.
|
232
|
+
# @!scope class
|
233
|
+
#
|
234
|
+
# @param url [String] The optional String base URL to use as a prefix for
|
235
|
+
# all requests. Can also be the options Hash.
|
236
|
+
# @param body [String] body for the request.
|
237
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
238
|
+
#
|
239
|
+
# @example
|
240
|
+
# conn.post '/items', data, content_type: 'application/json'
|
167
241
|
#
|
168
242
|
# # Simple ElasticSearch indexing sample.
|
169
243
|
# conn.post '/twitter/tweet' do |req|
|
170
244
|
# req.headers[:content_type] = 'application/json'
|
171
245
|
# req.params[:routing] = 'kimchy'
|
172
|
-
# req.body = JSON.generate(:
|
246
|
+
# req.body = JSON.generate(user: 'kimchy', ...)
|
173
247
|
# end
|
174
248
|
#
|
175
|
-
#
|
176
|
-
#
|
249
|
+
# @yield [Faraday::Request] for further request customizations
|
250
|
+
# @return [Faraday::Response]
|
251
|
+
|
252
|
+
# @!method put(url = nil, body = nil, headers = nil)
|
253
|
+
# Makes a PUT HTTP request with a body.
|
254
|
+
# @!scope class
|
177
255
|
#
|
178
|
-
#
|
256
|
+
# @param url [String] The optional String base URL to use as a prefix for
|
257
|
+
# all requests. Can also be the options Hash.
|
258
|
+
# @param body [String] body for the request.
|
259
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
179
260
|
#
|
180
|
-
#
|
261
|
+
# @example
|
262
|
+
# # TODO: Make it a PUT example
|
263
|
+
# conn.post '/items', data, content_type: 'application/json'
|
181
264
|
#
|
182
|
-
#
|
183
|
-
|
265
|
+
# # Simple ElasticSearch indexing sample.
|
266
|
+
# conn.post '/twitter/tweet' do |req|
|
267
|
+
# req.headers[:content_type] = 'application/json'
|
268
|
+
# req.params[:routing] = 'kimchy'
|
269
|
+
# req.body = JSON.generate(user: 'kimchy', ...)
|
270
|
+
# end
|
271
|
+
#
|
272
|
+
# @yield [Faraday::Request] for further request customizations
|
273
|
+
# @return [Faraday::Response]
|
274
|
+
|
275
|
+
# @!visibility private
|
276
|
+
METHODS_WITH_BODY.each do |method|
|
184
277
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
185
278
|
def #{method}(url = nil, body = nil, headers = nil, &block)
|
186
279
|
run_request(:#{method}, url, body, headers, &block)
|
@@ -188,123 +281,126 @@ module Faraday
|
|
188
281
|
RUBY
|
189
282
|
end
|
190
283
|
|
191
|
-
#
|
284
|
+
# Sets up the Authorization header with these credentials, encoded
|
192
285
|
# with base64.
|
193
286
|
#
|
194
|
-
# login
|
195
|
-
# pass
|
287
|
+
# @param login [String] The authentication login.
|
288
|
+
# @param pass [String] The authentication password.
|
196
289
|
#
|
197
|
-
#
|
290
|
+
# @example
|
198
291
|
#
|
199
292
|
# conn.basic_auth 'Aladdin', 'open sesame'
|
200
293
|
# conn.headers['Authorization']
|
201
294
|
# # => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
|
202
295
|
#
|
203
|
-
#
|
296
|
+
# @return [void]
|
204
297
|
def basic_auth(login, pass)
|
205
298
|
set_authorization_header(:basic_auth, login, pass)
|
206
299
|
end
|
207
300
|
|
208
|
-
#
|
301
|
+
# Sets up the Authorization header with the given token.
|
209
302
|
#
|
210
|
-
# token
|
211
|
-
# options
|
303
|
+
# @param token [String]
|
304
|
+
# @param options [Hash] extra token options.
|
212
305
|
#
|
213
|
-
#
|
306
|
+
# @example
|
214
307
|
#
|
215
|
-
# conn.token_auth 'abcdef', :
|
308
|
+
# conn.token_auth 'abcdef', foo: 'bar'
|
216
309
|
# conn.headers['Authorization']
|
217
310
|
# # => "Token token=\"abcdef\",
|
218
311
|
# foo=\"bar\""
|
219
312
|
#
|
220
|
-
#
|
313
|
+
# @return [void]
|
221
314
|
def token_auth(token, options = nil)
|
222
315
|
set_authorization_header(:token_auth, token, options)
|
223
316
|
end
|
224
317
|
|
225
|
-
#
|
318
|
+
# Sets up a custom Authorization header.
|
226
319
|
#
|
227
|
-
# type
|
228
|
-
# token
|
229
|
-
# a Hash is encoded into comma
|
320
|
+
# @param type [String] authorization type
|
321
|
+
# @param token [String, Hash] token. A String value is taken literally, and
|
322
|
+
# a Hash is encoded into comma-separated key/value pairs.
|
230
323
|
#
|
231
|
-
#
|
324
|
+
# @example
|
232
325
|
#
|
233
326
|
# conn.authorization :Bearer, 'mF_9.B5f-4.1JqM'
|
234
327
|
# conn.headers['Authorization']
|
235
328
|
# # => "Bearer mF_9.B5f-4.1JqM"
|
236
329
|
#
|
237
|
-
# conn.authorization :Token, :
|
330
|
+
# conn.authorization :Token, token: 'abcdef', foo: 'bar'
|
238
331
|
# conn.headers['Authorization']
|
239
332
|
# # => "Token token=\"abcdef\",
|
240
333
|
# foo=\"bar\""
|
241
334
|
#
|
242
|
-
#
|
335
|
+
# @return [void]
|
243
336
|
def authorization(type, token)
|
244
337
|
set_authorization_header(:authorization, type, token)
|
245
338
|
end
|
246
339
|
|
247
|
-
#
|
248
|
-
# parallel-capable adapter.
|
340
|
+
# Check if the adapter is parallel-capable.
|
249
341
|
#
|
250
|
-
#
|
342
|
+
# @yield if the adapter isn't parallel-capable, or if no adapter is set yet.
|
251
343
|
#
|
252
|
-
#
|
344
|
+
# @return [Object, nil] a parallel manager or nil if yielded
|
345
|
+
# @api private
|
253
346
|
def default_parallel_manager
|
254
347
|
@default_parallel_manager ||= begin
|
255
|
-
|
256
|
-
h.klass.respond_to?(:supports_parallel?) and h.klass.supports_parallel?
|
257
|
-
end
|
348
|
+
adapter = @builder.adapter.klass if @builder.adapter
|
258
349
|
|
259
|
-
if
|
260
|
-
|
350
|
+
if support_parallel?(adapter)
|
351
|
+
adapter.setup_parallel_manager
|
261
352
|
elsif block_given?
|
262
353
|
yield
|
263
354
|
end
|
264
355
|
end
|
265
356
|
end
|
266
357
|
|
267
|
-
#
|
358
|
+
# Determine if this Faraday::Connection can make parallel requests.
|
268
359
|
#
|
269
|
-
#
|
360
|
+
# @return [Boolean]
|
270
361
|
def in_parallel?
|
271
362
|
!!@parallel_manager
|
272
363
|
end
|
273
364
|
|
274
|
-
#
|
365
|
+
# Sets up the parallel manager to make a set of requests.
|
275
366
|
#
|
276
|
-
# manager
|
367
|
+
# @param manager [Object] The parallel manager that this Connection's
|
368
|
+
# Adapter uses.
|
277
369
|
#
|
278
|
-
#
|
279
|
-
#
|
370
|
+
# @yield a block to execute multiple requests.
|
371
|
+
# @return [void]
|
280
372
|
def in_parallel(manager = nil)
|
281
|
-
@parallel_manager = manager || default_parallel_manager
|
282
|
-
warn
|
283
|
-
|
373
|
+
@parallel_manager = manager || default_parallel_manager do
|
374
|
+
warn 'Warning: `in_parallel` called but no parallel-capable adapter ' \
|
375
|
+
'on Faraday stack'
|
376
|
+
warn caller[2, 10].join("\n")
|
284
377
|
nil
|
285
|
-
|
378
|
+
end
|
286
379
|
yield
|
287
|
-
@parallel_manager
|
380
|
+
@parallel_manager&.run
|
288
381
|
ensure
|
289
382
|
@parallel_manager = nil
|
290
383
|
end
|
291
384
|
|
292
|
-
#
|
293
|
-
|
294
|
-
|
295
|
-
|
385
|
+
# Sets the Hash proxy options.
|
386
|
+
#
|
387
|
+
# @param new_value [Object]
|
388
|
+
def proxy=(new_value)
|
389
|
+
@manual_proxy = true
|
390
|
+
@proxy = new_value ? ProxyOptions.from(new_value) : nil
|
296
391
|
end
|
297
392
|
|
298
393
|
def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port=
|
299
394
|
def_delegator :url_prefix, :path, :path_prefix
|
300
395
|
|
301
|
-
#
|
302
|
-
# components in this connection.
|
396
|
+
# Parses the given URL with URI and stores the individual
|
397
|
+
# components in this connection. These components serve as defaults for
|
303
398
|
# requests made by this connection.
|
304
399
|
#
|
305
|
-
# url
|
400
|
+
# @param url [String, URI]
|
401
|
+
# @param encoder [Object]
|
306
402
|
#
|
307
|
-
#
|
403
|
+
# @example
|
308
404
|
#
|
309
405
|
# conn = Faraday::Connection.new { ... }
|
310
406
|
# conn.url_prefix = "https://sushi.com/api"
|
@@ -312,8 +408,6 @@ module Faraday
|
|
312
408
|
# conn.path_prefix # => "/api"
|
313
409
|
#
|
314
410
|
# conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
|
315
|
-
#
|
316
|
-
# Returns the parsed URI from teh given input..
|
317
411
|
def url_prefix=(url, encoder = nil)
|
318
412
|
uri = @url_prefix = Utils.URI(url)
|
319
413
|
self.path_prefix = uri.path
|
@@ -325,58 +419,70 @@ module Faraday
|
|
325
419
|
basic_auth user, password
|
326
420
|
uri.user = uri.password = nil
|
327
421
|
end
|
328
|
-
|
329
|
-
uri
|
330
422
|
end
|
331
423
|
|
332
|
-
#
|
424
|
+
# Sets the path prefix and ensures that it always has a leading
|
333
425
|
# slash.
|
334
426
|
#
|
335
|
-
# value
|
427
|
+
# @param value [String]
|
336
428
|
#
|
337
|
-
#
|
429
|
+
# @return [String] the new path prefix
|
338
430
|
def path_prefix=(value)
|
339
431
|
url_prefix.path = if value
|
340
|
-
|
341
|
-
|
342
|
-
|
432
|
+
value = "/#{value}" unless value[0, 1] == '/'
|
433
|
+
value
|
434
|
+
end
|
343
435
|
end
|
344
436
|
|
345
|
-
#
|
437
|
+
# Takes a relative url for a request and combines it with the defaults
|
346
438
|
# set on the connection instance.
|
347
439
|
#
|
440
|
+
# @param url [String]
|
441
|
+
# @param extra_params [Hash]
|
442
|
+
#
|
443
|
+
# @example
|
348
444
|
# conn = Faraday::Connection.new { ... }
|
349
445
|
# conn.url_prefix = "https://sushi.com/api?token=abc"
|
350
446
|
# conn.scheme # => https
|
351
447
|
# conn.path_prefix # => "/api"
|
352
448
|
#
|
353
|
-
# conn.build_url("nigiri?page=2")
|
354
|
-
#
|
449
|
+
# conn.build_url("nigiri?page=2")
|
450
|
+
# # => https://sushi.com/api/nigiri?token=abc&page=2
|
451
|
+
#
|
452
|
+
# conn.build_url("nigiri", page: 2)
|
453
|
+
# # => https://sushi.com/api/nigiri?token=abc&page=2
|
355
454
|
#
|
356
455
|
def build_url(url = nil, extra_params = nil)
|
357
456
|
uri = build_exclusive_url(url)
|
358
457
|
|
359
458
|
query_values = params.dup.merge_query(uri.query, options.params_encoder)
|
360
|
-
query_values.update
|
361
|
-
uri.query =
|
459
|
+
query_values.update(extra_params) if extra_params
|
460
|
+
uri.query =
|
461
|
+
if query_values.empty?
|
462
|
+
nil
|
463
|
+
else
|
464
|
+
query_values.to_query(options.params_encoder)
|
465
|
+
end
|
362
466
|
|
363
467
|
uri
|
364
468
|
end
|
365
469
|
|
366
470
|
# Builds and runs the Faraday::Request.
|
367
471
|
#
|
368
|
-
# method
|
369
|
-
# url
|
370
|
-
# body
|
371
|
-
#
|
472
|
+
# @param method [Symbol] HTTP method.
|
473
|
+
# @param url [String, URI] String or URI to access.
|
474
|
+
# @param body [Object] The request body that will eventually be converted to
|
475
|
+
# a string.
|
476
|
+
# @param headers [Hash] unencoded HTTP header key/value pairs.
|
372
477
|
#
|
373
|
-
#
|
478
|
+
# @return [Faraday::Response]
|
374
479
|
def run_request(method, url, body, headers)
|
375
|
-
|
480
|
+
unless METHODS.include?(method)
|
376
481
|
raise ArgumentError, "unknown http method: #{method}"
|
377
482
|
end
|
378
483
|
|
379
484
|
request = build_request(method) do |req|
|
485
|
+
req.options.proxy = proxy_for_request(url)
|
380
486
|
req.url(url) if url
|
381
487
|
req.headers.update(headers) if headers
|
382
488
|
req.body = body if body
|
@@ -388,68 +494,121 @@ module Faraday
|
|
388
494
|
|
389
495
|
# Creates and configures the request object.
|
390
496
|
#
|
391
|
-
#
|
497
|
+
# @param method [Symbol]
|
498
|
+
#
|
499
|
+
# @yield [Faraday::Request] if block given
|
500
|
+
# @return [Faraday::Request]
|
392
501
|
def build_request(method)
|
393
502
|
Request.create(method) do |req|
|
394
|
-
req.params =
|
395
|
-
req.headers =
|
396
|
-
req.options =
|
503
|
+
req.params = params.dup
|
504
|
+
req.headers = headers.dup
|
505
|
+
req.options = options.dup
|
397
506
|
yield(req) if block_given?
|
398
507
|
end
|
399
508
|
end
|
400
509
|
|
401
|
-
#
|
510
|
+
# Build an absolute URL based on url_prefix.
|
402
511
|
#
|
403
|
-
# url
|
404
|
-
# params
|
512
|
+
# @param url [String, URI]
|
513
|
+
# @param params [Faraday::Utils::ParamsHash] A Faraday::Utils::ParamsHash to
|
514
|
+
# replace the query values
|
405
515
|
# of the resulting url (default: nil).
|
406
516
|
#
|
407
|
-
#
|
517
|
+
# @return [URI]
|
408
518
|
def build_exclusive_url(url = nil, params = nil, params_encoder = nil)
|
409
|
-
url = nil if url.respond_to?(:empty?)
|
519
|
+
url = nil if url.respond_to?(:empty?) && url.empty?
|
410
520
|
base = url_prefix
|
411
|
-
if url
|
521
|
+
if url && base.path && base.path !~ %r{/$}
|
412
522
|
base = base.dup
|
413
|
-
base.path = base.path
|
523
|
+
base.path = "#{base.path}/" # ensure trailing slash
|
414
524
|
end
|
415
525
|
uri = url ? base + url : base
|
416
|
-
|
417
|
-
|
526
|
+
if params
|
527
|
+
uri.query = params.to_query(params_encoder || options.params_encoder)
|
528
|
+
end
|
529
|
+
# rubocop:disable Style/SafeNavigation
|
530
|
+
uri.query = nil if uri.query && uri.query.empty?
|
531
|
+
# rubocop:enable Style/SafeNavigation
|
418
532
|
uri
|
419
533
|
end
|
420
534
|
|
421
|
-
#
|
535
|
+
# Creates a duplicate of this Faraday::Connection.
|
422
536
|
#
|
423
|
-
#
|
537
|
+
# @api private
|
538
|
+
#
|
539
|
+
# @return [Faraday::Connection]
|
424
540
|
def dup
|
425
541
|
self.class.new(build_exclusive_url,
|
426
|
-
:
|
427
|
-
:
|
428
|
-
:
|
429
|
-
:
|
430
|
-
:
|
542
|
+
headers: headers.dup,
|
543
|
+
params: params.dup,
|
544
|
+
builder: builder.dup,
|
545
|
+
ssl: ssl.dup,
|
546
|
+
request: options.dup)
|
431
547
|
end
|
432
548
|
|
433
|
-
#
|
549
|
+
# Yields username and password extracted from a URI if they both exist.
|
550
|
+
#
|
551
|
+
# @param uri [URI]
|
552
|
+
# @yield [username, password] any username and password
|
553
|
+
# @yieldparam username [String] any username from URI
|
554
|
+
# @yieldparam password [String] any password from URI
|
555
|
+
# @return [void]
|
556
|
+
# @api private
|
434
557
|
def with_uri_credentials(uri)
|
435
|
-
|
436
|
-
|
437
|
-
|
558
|
+
return unless uri.user && uri.password
|
559
|
+
|
560
|
+
yield(Utils.unescape(uri.user), Utils.unescape(uri.password))
|
438
561
|
end
|
439
562
|
|
440
563
|
def set_authorization_header(header_type, *args)
|
441
|
-
header = Faraday::Request
|
442
|
-
|
564
|
+
header = Faraday::Request
|
565
|
+
.lookup_middleware(header_type)
|
566
|
+
.header(*args)
|
567
|
+
|
443
568
|
headers[Faraday::Request::Authorization::KEY] = header
|
444
569
|
end
|
445
570
|
|
571
|
+
def proxy_from_env(url)
|
572
|
+
return if Faraday.ignore_env_proxy
|
573
|
+
|
574
|
+
uri = nil
|
575
|
+
if URI.parse('').respond_to?(:find_proxy)
|
576
|
+
case url
|
577
|
+
when String
|
578
|
+
uri = Utils.URI(url)
|
579
|
+
uri = URI.parse("#{uri.scheme}://#{uri.hostname}").find_proxy
|
580
|
+
when URI
|
581
|
+
uri = url.find_proxy
|
582
|
+
when nil
|
583
|
+
uri = find_default_proxy
|
584
|
+
end
|
585
|
+
else
|
586
|
+
warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
|
587
|
+
uri = find_default_proxy
|
588
|
+
end
|
589
|
+
ProxyOptions.from(uri) if uri
|
590
|
+
end
|
591
|
+
|
446
592
|
def find_default_proxy
|
447
|
-
warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
|
448
593
|
uri = ENV['http_proxy']
|
449
|
-
|
450
|
-
|
451
|
-
|
594
|
+
return unless uri && !uri.empty?
|
595
|
+
|
596
|
+
uri = "http://#{uri}" unless uri.match?(/^http/i)
|
597
|
+
uri
|
598
|
+
end
|
599
|
+
|
600
|
+
def proxy_for_request(url)
|
601
|
+
return proxy if @manual_proxy
|
602
|
+
|
603
|
+
if url && Utils.URI(url).absolute?
|
604
|
+
proxy_from_env(url)
|
605
|
+
else
|
606
|
+
proxy
|
452
607
|
end
|
453
608
|
end
|
609
|
+
|
610
|
+
def support_parallel?(adapter)
|
611
|
+
adapter&.respond_to?(:supports_parallel?) && adapter&.supports_parallel?
|
612
|
+
end
|
454
613
|
end
|
455
614
|
end
|