faraday 0.7.4 → 1.0.1
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 +276 -0
- data/LICENSE.md +1 -1
- data/README.md +40 -153
- data/Rakefile +4 -139
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday/adapter/em_http.rb +286 -0
- data/lib/faraday/adapter/em_http_ssl_patch.rb +62 -0
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +69 -0
- data/lib/faraday/adapter/em_synchrony.rb +120 -36
- data/lib/faraday/adapter/excon.rb +108 -12
- data/lib/faraday/adapter/httpclient.rb +152 -0
- data/lib/faraday/adapter/net_http.rb +187 -43
- data/lib/faraday/adapter/net_http_persistent.rb +91 -0
- data/lib/faraday/adapter/patron.rb +106 -10
- data/lib/faraday/adapter/rack.rb +75 -0
- data/lib/faraday/adapter/test.rb +160 -61
- data/lib/faraday/adapter/typhoeus.rb +7 -46
- data/lib/faraday/adapter.rb +105 -33
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +95 -0
- data/lib/faraday/connection.rb +525 -157
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
- data/lib/faraday/error.rb +122 -30
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/middleware.rb +14 -22
- data/lib/faraday/middleware_registry.rb +129 -0
- 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/options.rb +222 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +5 -0
- data/lib/faraday/rack_builder.rb +248 -0
- data/lib/faraday/request/authorization.rb +55 -0
- data/lib/faraday/request/basic_authentication.rb +20 -0
- data/lib/faraday/request/instrumentation.rb +54 -0
- data/lib/faraday/request/multipart.rb +84 -48
- data/lib/faraday/request/retry.rb +239 -0
- data/lib/faraday/request/token_authentication.rb +20 -0
- data/lib/faraday/request/url_encoded.rb +46 -27
- data/lib/faraday/request.rb +112 -50
- data/lib/faraday/response/logger.rb +24 -25
- data/lib/faraday/response/raise_error.rb +40 -11
- data/lib/faraday/response.rb +44 -35
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +72 -117
- data/lib/faraday.rb +142 -64
- 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/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 +45 -0
- data/spec/faraday/middleware_spec.rb +26 -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 +34 -0
- data/spec/faraday/params_encoders/nested_spec.rb +134 -0
- data/spec/faraday/rack_builder_spec.rb +196 -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 +274 -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 +109 -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 +106 -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 +104 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +234 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +126 -126
- data/Gemfile +0 -29
- data/config.ru +0 -6
- data/faraday.gemspec +0 -92
- data/lib/faraday/adapter/action_dispatch.rb +0 -29
- data/lib/faraday/builder.rb +0 -160
- data/lib/faraday/request/json.rb +0 -35
- data/lib/faraday/upload_io.rb +0 -23
- data/test/adapters/live_test.rb +0 -205
- data/test/adapters/logger_test.rb +0 -37
- data/test/adapters/net_http_test.rb +0 -33
- data/test/adapters/test_middleware_test.rb +0 -70
- data/test/connection_test.rb +0 -254
- data/test/env_test.rb +0 -158
- data/test/helper.rb +0 -41
- data/test/live_server.rb +0 -45
- data/test/middleware_stack_test.rb +0 -118
- data/test/request_middleware_test.rb +0 -116
- data/test/response_middleware_test.rb +0 -74
data/lib/faraday/response.rb
CHANGED
|
@@ -1,98 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'forwardable'
|
|
2
4
|
|
|
3
5
|
module Faraday
|
|
6
|
+
# Response represents an HTTP response from making an HTTP request.
|
|
4
7
|
class Response
|
|
5
8
|
# Used for simple response middleware.
|
|
6
9
|
class Middleware < Faraday::Middleware
|
|
7
10
|
def call(env)
|
|
8
|
-
@app.call(env).on_complete do |
|
|
9
|
-
on_complete(
|
|
11
|
+
@app.call(env).on_complete do |environment|
|
|
12
|
+
on_complete(environment)
|
|
10
13
|
end
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
# Override this to modify the environment after the response has finished.
|
|
14
17
|
# Calls the `parse` method if defined
|
|
18
|
+
# `parse` method can be defined as private, public and protected
|
|
15
19
|
def on_complete(env)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
return unless respond_to?(:parse, true) && env.parse_body?
|
|
21
|
+
|
|
22
|
+
env.body = parse(env.body)
|
|
19
23
|
end
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
extend Forwardable
|
|
23
|
-
extend
|
|
27
|
+
extend MiddlewareRegistry
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
register_lookup_modules \
|
|
30
|
-
:raise_error => :RaiseError,
|
|
31
|
-
:logger => :Logger
|
|
29
|
+
register_middleware File.expand_path('response', __dir__),
|
|
30
|
+
raise_error: [:RaiseError, 'raise_error'],
|
|
31
|
+
logger: [:Logger, 'logger']
|
|
32
32
|
|
|
33
33
|
def initialize(env = nil)
|
|
34
|
-
@env = env
|
|
34
|
+
@env = Env.from(env) if env
|
|
35
35
|
@on_complete_callbacks = []
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
attr_reader :env
|
|
39
|
-
alias_method :to_hash, :env
|
|
40
39
|
|
|
41
40
|
def status
|
|
42
|
-
finished? ? env
|
|
41
|
+
finished? ? env.status : nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reason_phrase
|
|
45
|
+
finished? ? env.reason_phrase : nil
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
def headers
|
|
46
|
-
finished? ? env
|
|
49
|
+
finished? ? env.response_headers : {}
|
|
47
50
|
end
|
|
48
51
|
def_delegator :headers, :[]
|
|
49
52
|
|
|
50
53
|
def body
|
|
51
|
-
finished? ? env
|
|
54
|
+
finished? ? env.body : nil
|
|
52
55
|
end
|
|
53
56
|
|
|
54
57
|
def finished?
|
|
55
58
|
!!env
|
|
56
59
|
end
|
|
57
60
|
|
|
58
|
-
def on_complete
|
|
59
|
-
if
|
|
60
|
-
@on_complete_callbacks <<
|
|
61
|
+
def on_complete(&block)
|
|
62
|
+
if !finished?
|
|
63
|
+
@on_complete_callbacks << block
|
|
61
64
|
else
|
|
62
|
-
yield
|
|
65
|
+
yield(env)
|
|
63
66
|
end
|
|
64
|
-
|
|
67
|
+
self
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
def finish(env)
|
|
68
|
-
raise
|
|
69
|
-
|
|
70
|
-
@
|
|
71
|
-
|
|
71
|
+
raise 'response already finished' if finished?
|
|
72
|
+
|
|
73
|
+
@env = env.is_a?(Env) ? env : Env.from(env)
|
|
74
|
+
@on_complete_callbacks.each { |callback| callback.call(@env) }
|
|
75
|
+
self
|
|
72
76
|
end
|
|
73
77
|
|
|
74
78
|
def success?
|
|
75
|
-
|
|
79
|
+
finished? && env.success?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def to_hash
|
|
83
|
+
{
|
|
84
|
+
status: env.status, body: env.body,
|
|
85
|
+
response_headers: env.response_headers
|
|
86
|
+
}
|
|
76
87
|
end
|
|
77
88
|
|
|
78
89
|
# because @on_complete_callbacks cannot be marshalled
|
|
79
90
|
def marshal_dump
|
|
80
|
-
|
|
81
|
-
:status => @env[:status], :body => @env[:body],
|
|
82
|
-
:response_headers => @env[:response_headers]
|
|
83
|
-
}
|
|
91
|
+
finished? ? to_hash : nil
|
|
84
92
|
end
|
|
85
93
|
|
|
86
94
|
def marshal_load(env)
|
|
87
|
-
@env = env
|
|
95
|
+
@env = Env.from(env)
|
|
88
96
|
end
|
|
89
97
|
|
|
90
98
|
# Expand the env with more properties, without overriding existing ones.
|
|
91
99
|
# Useful for applying request params after restoring a marshalled Response.
|
|
92
100
|
def apply_request(request_env)
|
|
93
101
|
raise "response didn't finish yet" unless finished?
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
|
|
103
|
+
@env = Env.from(request_env).update(@env)
|
|
104
|
+
self
|
|
96
105
|
end
|
|
97
106
|
end
|
|
98
107
|
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Faraday
|
|
4
|
+
module Utils
|
|
5
|
+
# A case-insensitive Hash that preserves the original case of a header
|
|
6
|
+
# when set.
|
|
7
|
+
#
|
|
8
|
+
# Adapted from Rack::Utils::HeaderHash
|
|
9
|
+
class Headers < ::Hash
|
|
10
|
+
def self.from(value)
|
|
11
|
+
new(value)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.allocate
|
|
15
|
+
new_self = super
|
|
16
|
+
new_self.initialize_names
|
|
17
|
+
new_self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def initialize(hash = nil)
|
|
21
|
+
super()
|
|
22
|
+
@names = {}
|
|
23
|
+
update(hash || {})
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize_names
|
|
27
|
+
@names = {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# on dup/clone, we need to duplicate @names hash
|
|
31
|
+
def initialize_copy(other)
|
|
32
|
+
super
|
|
33
|
+
@names = other.names.dup
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# need to synchronize concurrent writes to the shared KeyMap
|
|
37
|
+
keymap_mutex = Mutex.new
|
|
38
|
+
|
|
39
|
+
# symbol -> string mapper + cache
|
|
40
|
+
KeyMap = Hash.new do |map, key|
|
|
41
|
+
value = if key.respond_to?(:to_str)
|
|
42
|
+
key
|
|
43
|
+
else
|
|
44
|
+
key.to_s.split('_') # user_agent: %w(user agent)
|
|
45
|
+
.each(&:capitalize!) # => %w(User Agent)
|
|
46
|
+
.join('-') # => "User-Agent"
|
|
47
|
+
end
|
|
48
|
+
keymap_mutex.synchronize { map[key] = value }
|
|
49
|
+
end
|
|
50
|
+
KeyMap[:etag] = 'ETag'
|
|
51
|
+
|
|
52
|
+
def [](key)
|
|
53
|
+
key = KeyMap[key]
|
|
54
|
+
super(key) || super(@names[key.downcase])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def []=(key, val)
|
|
58
|
+
key = KeyMap[key]
|
|
59
|
+
key = (@names[key.downcase] ||= key)
|
|
60
|
+
# join multiple values with a comma
|
|
61
|
+
val = val.to_ary.join(', ') if val.respond_to?(:to_ary)
|
|
62
|
+
super(key, val)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def fetch(key, *args, &block)
|
|
66
|
+
key = KeyMap[key]
|
|
67
|
+
key = @names.fetch(key.downcase, key)
|
|
68
|
+
super(key, *args, &block)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def delete(key)
|
|
72
|
+
key = KeyMap[key]
|
|
73
|
+
key = @names[key.downcase]
|
|
74
|
+
return unless key
|
|
75
|
+
|
|
76
|
+
@names.delete key.downcase
|
|
77
|
+
super(key)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def include?(key)
|
|
81
|
+
@names.include? key.downcase
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
alias has_key? include?
|
|
85
|
+
alias member? include?
|
|
86
|
+
alias key? include?
|
|
87
|
+
|
|
88
|
+
def merge!(other)
|
|
89
|
+
other.each { |k, v| self[k] = v }
|
|
90
|
+
self
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
alias update merge!
|
|
94
|
+
|
|
95
|
+
def merge(other)
|
|
96
|
+
hash = dup
|
|
97
|
+
hash.merge! other
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def replace(other)
|
|
101
|
+
clear
|
|
102
|
+
@names.clear
|
|
103
|
+
update other
|
|
104
|
+
self
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def to_hash
|
|
108
|
+
::Hash.new.update(self)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def parse(header_string)
|
|
112
|
+
return unless header_string && !header_string.empty?
|
|
113
|
+
|
|
114
|
+
headers = header_string.split(/\r\n/)
|
|
115
|
+
|
|
116
|
+
# Find the last set of response headers.
|
|
117
|
+
start_index = headers.rindex { |x| x.match(%r{^HTTP/}) } || 0
|
|
118
|
+
last_response = headers.slice(start_index, headers.size)
|
|
119
|
+
|
|
120
|
+
last_response
|
|
121
|
+
.tap { |a| a.shift if a.first.start_with?('HTTP/') }
|
|
122
|
+
.map { |h| h.split(/:\s*/, 2) } # split key and value
|
|
123
|
+
.reject { |p| p[0].nil? } # ignore blank lines
|
|
124
|
+
.each { |key, value| add_parsed(key, value) }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
protected
|
|
128
|
+
|
|
129
|
+
attr_reader :names
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
# Join multiple values with a comma.
|
|
134
|
+
def add_parsed(key, value)
|
|
135
|
+
self[key] ? self[key] << ', ' << value : self[key] = value
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Faraday
|
|
4
|
+
module Utils
|
|
5
|
+
# A hash with stringified keys.
|
|
6
|
+
class ParamsHash < Hash
|
|
7
|
+
def [](key)
|
|
8
|
+
super(convert_key(key))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def []=(key, value)
|
|
12
|
+
super(convert_key(key), value)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def delete(key)
|
|
16
|
+
super(convert_key(key))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def include?(key)
|
|
20
|
+
super(convert_key(key))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alias has_key? include?
|
|
24
|
+
alias member? include?
|
|
25
|
+
alias key? include?
|
|
26
|
+
|
|
27
|
+
def update(params)
|
|
28
|
+
params.each do |key, value|
|
|
29
|
+
self[key] = value
|
|
30
|
+
end
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
alias merge! update
|
|
34
|
+
|
|
35
|
+
def merge(params)
|
|
36
|
+
dup.update(params)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def replace(other)
|
|
40
|
+
clear
|
|
41
|
+
update(other)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def merge_query(query, encoder = nil)
|
|
45
|
+
return self unless query && !query.empty?
|
|
46
|
+
|
|
47
|
+
update((encoder || Utils.default_params_encoder).decode(query))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_query(encoder = nil)
|
|
51
|
+
(encoder || Utils.default_params_encoder).encode(self)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def convert_key(key)
|
|
57
|
+
key.to_s
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/faraday/utils.rb
CHANGED
|
@@ -1,149 +1,106 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday/utils/headers'
|
|
4
|
+
require 'faraday/utils/params_hash'
|
|
2
5
|
|
|
3
6
|
module Faraday
|
|
7
|
+
# Utils contains various static helper methods.
|
|
4
8
|
module Utils
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
extend Rack::Utils
|
|
8
|
-
extend self
|
|
9
|
-
|
|
10
|
-
class Headers < HeaderHash
|
|
11
|
-
# symbol -> string mapper + cache
|
|
12
|
-
KeyMap = Hash.new do |map, key|
|
|
13
|
-
map[key] = if key.respond_to?(:to_str) then key
|
|
14
|
-
else
|
|
15
|
-
key.to_s.split('_'). # :user_agent => %w(user agent)
|
|
16
|
-
each { |w| w.capitalize! }. # => %w(User Agent)
|
|
17
|
-
join('-') # => "User-Agent"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
KeyMap[:etag] = "ETag"
|
|
21
|
-
|
|
22
|
-
def [](k)
|
|
23
|
-
super(KeyMap[k])
|
|
24
|
-
end
|
|
9
|
+
module_function
|
|
25
10
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
v = v.to_ary.join(', ') if v.respond_to? :to_ary
|
|
29
|
-
super(KeyMap[k], v)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
alias_method :update, :merge!
|
|
33
|
-
|
|
34
|
-
def parse(header_string)
|
|
35
|
-
return unless header_string && !header_string.empty?
|
|
36
|
-
header_string.split(/\r\n/).
|
|
37
|
-
tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
|
|
38
|
-
map { |h| h.split(/:\s+/, 2) }.reject { |(k, v)| k.nil? }. # split key and value, ignore blank lines
|
|
39
|
-
each { |key, value|
|
|
40
|
-
# join multiple values with a comma
|
|
41
|
-
if self[key] then self[key] << ', ' << value
|
|
42
|
-
else self[key] = value
|
|
43
|
-
end
|
|
44
|
-
}
|
|
45
|
-
end
|
|
11
|
+
def build_query(params)
|
|
12
|
+
FlatParamsEncoder.encode(params)
|
|
46
13
|
end
|
|
47
14
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
super(convert_key(key))
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def []=(key, value)
|
|
55
|
-
super(convert_key(key), value)
|
|
56
|
-
end
|
|
15
|
+
def build_nested_query(params)
|
|
16
|
+
NestedParamsEncoder.encode(params)
|
|
17
|
+
end
|
|
57
18
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
19
|
+
def default_space_encoding
|
|
20
|
+
@default_space_encoding ||= '+'
|
|
21
|
+
end
|
|
61
22
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
23
|
+
class << self
|
|
24
|
+
attr_writer :default_space_encoding
|
|
25
|
+
end
|
|
65
26
|
|
|
66
|
-
|
|
67
|
-
alias_method :member?, :include?
|
|
68
|
-
alias_method :key?, :include?
|
|
27
|
+
ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/.freeze
|
|
69
28
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
end
|
|
76
|
-
alias_method :merge!, :update
|
|
29
|
+
def escape(str)
|
|
30
|
+
str.to_s.gsub(ESCAPE_RE) do |match|
|
|
31
|
+
'%' + match.unpack('H2' * match.bytesize).join('%').upcase
|
|
32
|
+
end.gsub(' ', default_space_encoding)
|
|
33
|
+
end
|
|
77
34
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
35
|
+
def unescape(str)
|
|
36
|
+
CGI.unescape str.to_s
|
|
37
|
+
end
|
|
81
38
|
|
|
82
|
-
|
|
83
|
-
clear
|
|
84
|
-
update(other)
|
|
85
|
-
end
|
|
39
|
+
DEFAULT_SEP = /[&;] */n.freeze
|
|
86
40
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self
|
|
92
|
-
end
|
|
41
|
+
# Adapted from Rack
|
|
42
|
+
def parse_query(query)
|
|
43
|
+
FlatParamsEncoder.decode(query)
|
|
44
|
+
end
|
|
93
45
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
46
|
+
def parse_nested_query(query)
|
|
47
|
+
NestedParamsEncoder.decode(query)
|
|
48
|
+
end
|
|
97
49
|
|
|
98
|
-
|
|
50
|
+
def default_params_encoder
|
|
51
|
+
@default_params_encoder ||= NestedParamsEncoder
|
|
52
|
+
end
|
|
99
53
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
end
|
|
54
|
+
class << self
|
|
55
|
+
attr_writer :default_params_encoder
|
|
103
56
|
end
|
|
104
57
|
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
|
116
|
-
}.join("&")
|
|
117
|
-
when NilClass
|
|
118
|
-
prefix
|
|
58
|
+
# Normalize URI() behavior across Ruby versions
|
|
59
|
+
#
|
|
60
|
+
# url - A String or URI.
|
|
61
|
+
#
|
|
62
|
+
# Returns a parsed URI.
|
|
63
|
+
def URI(url) # rubocop:disable Naming/MethodName
|
|
64
|
+
if url.respond_to?(:host)
|
|
65
|
+
url
|
|
66
|
+
elsif url.respond_to?(:to_str)
|
|
67
|
+
default_uri_parser.call(url)
|
|
119
68
|
else
|
|
120
|
-
raise ArgumentError,
|
|
121
|
-
"#{prefix}=#{escape(value)}"
|
|
69
|
+
raise ArgumentError, 'bad argument (expected URI object or URI string)'
|
|
122
70
|
end
|
|
123
71
|
end
|
|
124
72
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
'%' << $1.unpack('H2'*bytesize($1)).join('%').tap { |c| c.upcase! }
|
|
73
|
+
def default_uri_parser
|
|
74
|
+
@default_uri_parser ||= begin
|
|
75
|
+
require 'uri'
|
|
76
|
+
Kernel.method(:URI)
|
|
130
77
|
end
|
|
131
78
|
end
|
|
132
79
|
|
|
133
|
-
|
|
80
|
+
def default_uri_parser=(parser)
|
|
81
|
+
@default_uri_parser = if parser.respond_to?(:call) || parser.nil?
|
|
82
|
+
parser
|
|
83
|
+
else
|
|
84
|
+
parser.method(:parse)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Receives a String or URI and returns just
|
|
89
|
+
# the path with the query string sorted.
|
|
134
90
|
def normalize_path(url)
|
|
135
|
-
|
|
136
|
-
(url.
|
|
91
|
+
url = URI(url)
|
|
92
|
+
(url.path.start_with?('/') ? url.path : '/' + url.path) +
|
|
93
|
+
(url.query ? "?#{sort_query_params(url.query)}" : '')
|
|
137
94
|
end
|
|
138
95
|
|
|
139
96
|
# Recursive hash update
|
|
140
97
|
def deep_merge!(target, hash)
|
|
141
98
|
hash.each do |key, value|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
99
|
+
target[key] = if value.is_a?(Hash) && target[key].is_a?(Hash)
|
|
100
|
+
deep_merge(target[key], value)
|
|
101
|
+
else
|
|
102
|
+
value
|
|
103
|
+
end
|
|
147
104
|
end
|
|
148
105
|
target
|
|
149
106
|
end
|
|
@@ -153,8 +110,6 @@ module Faraday
|
|
|
153
110
|
deep_merge!(source.dup, hash)
|
|
154
111
|
end
|
|
155
112
|
|
|
156
|
-
protected
|
|
157
|
-
|
|
158
113
|
def sort_query_params(query)
|
|
159
114
|
query.split('&').sort.join('&')
|
|
160
115
|
end
|