faraday 0.17.3 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -8
  3. data/LICENSE.md +1 -1
  4. data/README.md +18 -358
  5. data/Rakefile +1 -7
  6. data/examples/client_spec.rb +65 -0
  7. data/examples/client_test.rb +79 -0
  8. data/lib/faraday.rb +94 -175
  9. data/lib/faraday/adapter.rb +82 -22
  10. data/lib/faraday/adapter/em_http.rb +142 -99
  11. data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
  12. data/lib/faraday/adapter/em_synchrony.rb +104 -60
  13. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
  14. data/lib/faraday/adapter/excon.rb +98 -56
  15. data/lib/faraday/adapter/httpclient.rb +83 -59
  16. data/lib/faraday/adapter/net_http.rb +130 -63
  17. data/lib/faraday/adapter/net_http_persistent.rb +50 -27
  18. data/lib/faraday/adapter/patron.rb +80 -43
  19. data/lib/faraday/adapter/rack.rb +30 -13
  20. data/lib/faraday/adapter/test.rb +86 -53
  21. data/lib/faraday/adapter/typhoeus.rb +4 -1
  22. data/lib/faraday/adapter_registry.rb +30 -0
  23. data/lib/faraday/autoload.rb +47 -36
  24. data/lib/faraday/connection.rb +312 -182
  25. data/lib/faraday/dependency_loader.rb +37 -0
  26. data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
  27. data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
  28. data/lib/faraday/error.rb +9 -35
  29. data/lib/faraday/file_part.rb +128 -0
  30. data/lib/faraday/logging/formatter.rb +105 -0
  31. data/lib/faraday/middleware.rb +12 -28
  32. data/lib/faraday/middleware_registry.rb +129 -0
  33. data/lib/faraday/options.rb +32 -183
  34. data/lib/faraday/options/connection_options.rb +22 -0
  35. data/lib/faraday/options/env.rb +181 -0
  36. data/lib/faraday/options/proxy_options.rb +28 -0
  37. data/lib/faraday/options/request_options.rb +22 -0
  38. data/lib/faraday/options/ssl_options.rb +59 -0
  39. data/lib/faraday/param_part.rb +53 -0
  40. data/lib/faraday/parameters.rb +4 -197
  41. data/lib/faraday/rack_builder.rb +66 -55
  42. data/lib/faraday/request.rb +68 -36
  43. data/lib/faraday/request/authorization.rb +44 -30
  44. data/lib/faraday/request/basic_authentication.rb +14 -7
  45. data/lib/faraday/request/instrumentation.rb +45 -27
  46. data/lib/faraday/request/multipart.rb +79 -48
  47. data/lib/faraday/request/retry.rb +197 -171
  48. data/lib/faraday/request/token_authentication.rb +15 -10
  49. data/lib/faraday/request/url_encoded.rb +43 -23
  50. data/lib/faraday/response.rb +24 -14
  51. data/lib/faraday/response/logger.rb +22 -69
  52. data/lib/faraday/response/raise_error.rb +38 -18
  53. data/lib/faraday/utils.rb +36 -245
  54. data/lib/faraday/utils/headers.rb +139 -0
  55. data/lib/faraday/utils/params_hash.rb +61 -0
  56. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  57. data/spec/faraday/adapter/em_http_spec.rb +47 -0
  58. data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
  59. data/spec/faraday/adapter/excon_spec.rb +49 -0
  60. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  61. data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
  62. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  63. data/spec/faraday/adapter/patron_spec.rb +18 -0
  64. data/spec/faraday/adapter/rack_spec.rb +8 -0
  65. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  66. data/spec/faraday/adapter_registry_spec.rb +28 -0
  67. data/spec/faraday/adapter_spec.rb +55 -0
  68. data/spec/faraday/composite_read_io_spec.rb +80 -0
  69. data/spec/faraday/connection_spec.rb +691 -0
  70. data/spec/faraday/error_spec.rb +0 -57
  71. data/spec/faraday/middleware_spec.rb +26 -0
  72. data/spec/faraday/options/env_spec.rb +70 -0
  73. data/spec/faraday/options/options_spec.rb +297 -0
  74. data/spec/faraday/options/proxy_options_spec.rb +37 -0
  75. data/spec/faraday/options/request_options_spec.rb +19 -0
  76. data/spec/faraday/params_encoders/flat_spec.rb +34 -0
  77. data/spec/faraday/params_encoders/nested_spec.rb +134 -0
  78. data/spec/faraday/rack_builder_spec.rb +196 -0
  79. data/spec/faraday/request/authorization_spec.rb +88 -0
  80. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  81. data/spec/faraday/request/multipart_spec.rb +274 -0
  82. data/spec/faraday/request/retry_spec.rb +242 -0
  83. data/spec/faraday/request/url_encoded_spec.rb +83 -0
  84. data/spec/faraday/request_spec.rb +109 -0
  85. data/spec/faraday/response/logger_spec.rb +220 -0
  86. data/spec/faraday/response/middleware_spec.rb +68 -0
  87. data/spec/faraday/response/raise_error_spec.rb +15 -15
  88. data/spec/faraday/response_spec.rb +75 -0
  89. data/spec/faraday/utils/headers_spec.rb +82 -0
  90. data/spec/faraday/utils_spec.rb +56 -0
  91. data/spec/faraday_spec.rb +37 -0
  92. data/spec/spec_helper.rb +63 -36
  93. data/spec/support/disabling_stub.rb +14 -0
  94. data/spec/support/fake_safe_buffer.rb +15 -0
  95. data/spec/support/helper_methods.rb +133 -0
  96. data/spec/support/shared_examples/adapter.rb +104 -0
  97. data/spec/support/shared_examples/params_encoder.rb +18 -0
  98. data/spec/support/shared_examples/request_method.rb +234 -0
  99. data/spec/support/streaming_response_checker.rb +35 -0
  100. data/spec/support/webmock_rack_app.rb +68 -0
  101. metadata +66 -38
  102. data/lib/faraday/deprecate.rb +0 -107
  103. data/lib/faraday/upload_io.rb +0 -67
  104. data/spec/faraday/deprecate_spec.rb +0 -69
  105. data/test/adapters/default_test.rb +0 -14
  106. data/test/adapters/em_http_test.rb +0 -30
  107. data/test/adapters/em_synchrony_test.rb +0 -32
  108. data/test/adapters/excon_test.rb +0 -30
  109. data/test/adapters/httpclient_test.rb +0 -34
  110. data/test/adapters/integration.rb +0 -263
  111. data/test/adapters/logger_test.rb +0 -136
  112. data/test/adapters/net_http_persistent_test.rb +0 -114
  113. data/test/adapters/net_http_test.rb +0 -79
  114. data/test/adapters/patron_test.rb +0 -40
  115. data/test/adapters/rack_test.rb +0 -38
  116. data/test/adapters/test_middleware_test.rb +0 -157
  117. data/test/adapters/typhoeus_test.rb +0 -38
  118. data/test/authentication_middleware_test.rb +0 -65
  119. data/test/composite_read_io_test.rb +0 -109
  120. data/test/connection_test.rb +0 -738
  121. data/test/env_test.rb +0 -268
  122. data/test/helper.rb +0 -75
  123. data/test/live_server.rb +0 -67
  124. data/test/middleware/instrumentation_test.rb +0 -88
  125. data/test/middleware/retry_test.rb +0 -282
  126. data/test/middleware_stack_test.rb +0 -260
  127. data/test/multibyte.txt +0 -1
  128. data/test/options_test.rb +0 -333
  129. data/test/parameters_test.rb +0 -157
  130. data/test/request_middleware_test.rb +0 -126
  131. data/test/response_middleware_test.rb +0 -72
  132. data/test/strawberry.rb +0 -2
  133. data/test/utils_test.rb +0 -98
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Allows to disable WebMock stubs
4
+ module DisablingStub
5
+ def disable
6
+ @disabled = true
7
+ end
8
+
9
+ def disabled?
10
+ @disabled
11
+ end
12
+
13
+ WebMock::RequestStub.prepend self
14
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # emulates ActiveSupport::SafeBuffer#gsub
4
+ FakeSafeBuffer = Struct.new(:string) do
5
+ def to_s
6
+ self
7
+ end
8
+
9
+ def gsub(regex)
10
+ string.gsub(regex) do
11
+ match, = $&, '' =~ /a/
12
+ yield(match)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'multipart_parser/reader'
4
+
5
+ module Faraday
6
+ module HelperMethods
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ def features(*features)
13
+ @features = features
14
+ end
15
+
16
+ def on_feature(name)
17
+ yield if block_given? && feature?(name)
18
+ end
19
+
20
+ def feature?(name)
21
+ if @features.nil?
22
+ superclass.feature?(name) if superclass.respond_to?(:feature?)
23
+ elsif @features.include?(name)
24
+ true
25
+ end
26
+ end
27
+
28
+ def method_with_body?(method)
29
+ METHODS_WITH_BODY.include?(method.to_s)
30
+ end
31
+ end
32
+
33
+ def ssl_mode?
34
+ ENV['SSL'] == 'yes'
35
+ end
36
+
37
+ def normalize(url)
38
+ Faraday::Utils::URI(url)
39
+ end
40
+
41
+ def with_default_uri_parser(parser)
42
+ old_parser = Faraday::Utils.default_uri_parser
43
+ begin
44
+ Faraday::Utils.default_uri_parser = parser
45
+ yield
46
+ ensure
47
+ Faraday::Utils.default_uri_parser = old_parser
48
+ end
49
+ end
50
+
51
+ def with_env(new_env)
52
+ old_env = {}
53
+
54
+ new_env.each do |key, value|
55
+ old_env[key] = ENV.fetch(key, false)
56
+ ENV[key] = value
57
+ end
58
+
59
+ begin
60
+ yield
61
+ ensure
62
+ old_env.each do |key, value|
63
+ value == false ? ENV.delete(key) : ENV[key] = value
64
+ end
65
+ end
66
+ end
67
+
68
+ def with_env_proxy_disabled
69
+ Faraday.ignore_env_proxy = true
70
+
71
+ begin
72
+ yield
73
+ ensure
74
+ Faraday.ignore_env_proxy = false
75
+ end
76
+ end
77
+
78
+ def capture_warnings
79
+ old = $stderr
80
+ $stderr = StringIO.new
81
+ begin
82
+ yield
83
+ $stderr.string
84
+ ensure
85
+ $stderr = old
86
+ end
87
+ end
88
+
89
+ def multipart_file
90
+ Faraday::FilePart.new(__FILE__, 'text/x-ruby')
91
+ end
92
+
93
+ # parse boundary out of a Content-Type header like:
94
+ # Content-Type: multipart/form-data; boundary=gc0p4Jq0M2Yt08jU534c0p
95
+ def parse_multipart_boundary(ctype)
96
+ MultipartParser::Reader.extract_boundary_value(ctype)
97
+ end
98
+
99
+ # parse a multipart MIME message, returning a hash of any multipart errors
100
+ def parse_multipart(boundary, body)
101
+ reader = MultipartParser::Reader.new(boundary)
102
+ result = { errors: [], parts: [] }
103
+ def result.part(name)
104
+ hash = self[:parts].detect { |h| h[:part].name == name }
105
+ [hash[:part], hash[:body].join]
106
+ end
107
+
108
+ reader.on_part do |part|
109
+ result[:parts] << thispart = {
110
+ part: part,
111
+ body: []
112
+ }
113
+ part.on_data do |chunk|
114
+ thispart[:body] << chunk
115
+ end
116
+ end
117
+ reader.on_error do |msg|
118
+ result[:errors] << msg
119
+ end
120
+ reader.write(body)
121
+ result
122
+ end
123
+
124
+ def method_with_body?(method)
125
+ self.class.method_with_body?(method)
126
+ end
127
+
128
+ def big_string
129
+ kb = 1024
130
+ (32..126).map(&:chr).cycle.take(50 * kb).join
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'an adapter' do |**options|
4
+ before { skip } if options[:skip]
5
+
6
+ context 'with SSL enabled' do
7
+ before { ENV['SSL'] = 'yes' }
8
+ include_examples 'adapter examples', options
9
+ end
10
+
11
+ context 'with SSL disabled' do
12
+ before { ENV['SSL'] = 'no' }
13
+ include_examples 'adapter examples', options
14
+ end
15
+ end
16
+
17
+ shared_examples 'adapter examples' do |**options|
18
+ include Faraday::StreamingResponseChecker
19
+
20
+ let(:adapter) { described_class.name.split('::').last }
21
+
22
+ let(:conn_options) { { headers: { 'X-Faraday-Adapter' => adapter } }.merge(options[:conn_options] || {}) }
23
+
24
+ let(:adapter_options) do
25
+ return [] unless options[:adapter_options]
26
+
27
+ if options[:adapter_options].is_a?(Array)
28
+ options[:adapter_options]
29
+ else
30
+ [options[:adapter_options]]
31
+ end
32
+ end
33
+
34
+ let(:protocol) { ssl_mode? ? 'https' : 'http' }
35
+ let(:remote) { "#{protocol}://example.com" }
36
+
37
+ let(:conn) do
38
+ conn_options[:ssl] ||= {}
39
+ conn_options[:ssl][:ca_file] ||= ENV['SSL_FILE']
40
+
41
+ Faraday.new(remote, conn_options) do |conn|
42
+ conn.request :multipart
43
+ conn.request :url_encoded
44
+ conn.response :raise_error
45
+ conn.adapter described_class, *adapter_options
46
+ end
47
+ end
48
+
49
+ let!(:request_stub) { stub_request(http_method, remote) }
50
+
51
+ after do
52
+ expect(request_stub).to have_been_requested unless request_stub.disabled?
53
+ end
54
+
55
+ describe '#delete' do
56
+ let(:http_method) { :delete }
57
+
58
+ it_behaves_like 'a request method', :delete
59
+ end
60
+
61
+ describe '#get' do
62
+ let(:http_method) { :get }
63
+
64
+ it_behaves_like 'a request method', :get
65
+ end
66
+
67
+ describe '#head' do
68
+ let(:http_method) { :head }
69
+
70
+ it_behaves_like 'a request method', :head
71
+ end
72
+
73
+ describe '#options' do
74
+ let(:http_method) { :options }
75
+
76
+ it_behaves_like 'a request method', :options
77
+ end
78
+
79
+ describe '#patch' do
80
+ let(:http_method) { :patch }
81
+
82
+ it_behaves_like 'a request method', :patch
83
+ end
84
+
85
+ describe '#post' do
86
+ let(:http_method) { :post }
87
+
88
+ it_behaves_like 'a request method', :post
89
+ end
90
+
91
+ describe '#put' do
92
+ let(:http_method) { :put }
93
+
94
+ it_behaves_like 'a request method', :put
95
+ end
96
+
97
+ on_feature :trace_method do
98
+ describe '#trace' do
99
+ let(:http_method) { :trace }
100
+
101
+ it_behaves_like 'a request method', :trace
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'a params encoder' do
4
+ it 'escapes safe buffer' do
5
+ monies = FakeSafeBuffer.new('$32,000.00')
6
+ expect(subject.encode('a' => monies)).to eq('a=%2432%2C000.00')
7
+ end
8
+
9
+ it 'raises type error for empty string' do
10
+ expect { subject.encode('') }.to raise_error(TypeError) do |error|
11
+ expect(error.message).to eq("Can't convert String into Hash.")
12
+ end
13
+ end
14
+
15
+ it 'encodes nil' do
16
+ expect(subject.encode('a' => nil)).to eq('a')
17
+ end
18
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'a request method' do |http_method|
4
+ let(:query_or_body) { method_with_body?(http_method) ? :body : :query }
5
+ let(:response) { conn.public_send(http_method, '/') }
6
+
7
+ unless http_method == :head && feature?(:skip_response_body_on_head)
8
+ it 'retrieves the response body' do
9
+ res_body = 'test'
10
+ request_stub.to_return(body: res_body)
11
+ expect(conn.public_send(http_method, '/').body).to eq(res_body)
12
+ end
13
+ end
14
+
15
+ it 'handles headers with multiple values' do
16
+ request_stub.to_return(headers: { 'Set-Cookie' => 'one, two' })
17
+ expect(response.headers['set-cookie']).to eq('one, two')
18
+ end
19
+
20
+ it 'retrieves the response headers' do
21
+ request_stub.to_return(headers: { 'Content-Type' => 'text/plain' })
22
+ expect(response.headers['Content-Type']).to match(%r{text/plain})
23
+ expect(response.headers['content-type']).to match(%r{text/plain})
24
+ end
25
+
26
+ it 'sends user agent' do
27
+ request_stub.with(headers: { 'User-Agent' => 'Agent Faraday' })
28
+ conn.public_send(http_method, '/', nil, user_agent: 'Agent Faraday')
29
+ end
30
+
31
+ it 'represents empty body response as blank string' do
32
+ expect(response.body).to eq('')
33
+ end
34
+
35
+ it 'handles connection error' do
36
+ request_stub.disable
37
+ expect { conn.public_send(http_method, 'http://localhost:4') }.to raise_error(Faraday::ConnectionFailed)
38
+ end
39
+
40
+ on_feature :local_socket_binding do
41
+ it 'binds local socket' do
42
+ stub_request(http_method, 'http://example.com')
43
+
44
+ host = '1.2.3.4'
45
+ port = 1234
46
+ conn_options[:request] = { bind: { host: host, port: port } }
47
+
48
+ conn.public_send(http_method, '/')
49
+
50
+ expect(conn.options[:bind][:host]).to eq(host)
51
+ expect(conn.options[:bind][:port]).to eq(port)
52
+ end
53
+ end
54
+
55
+ # context 'when wrong ssl certificate is provided' do
56
+ # let(:ca_file_path) { 'tmp/faraday-different-ca-cert.crt' }
57
+ # before { conn_options.merge!(ssl: { ca_file: ca_file_path }) }
58
+ #
59
+ # it do
60
+ # expect { conn.public_send(http_method, '/') }.to raise_error(Faraday::SSLError) # do |ex|
61
+ # expect(ex.message).to include?('certificate')
62
+ # end
63
+ # end
64
+ # end
65
+
66
+ on_feature :request_body_on_query_methods do
67
+ it 'sends request body' do
68
+ request_stub.with(Hash[:body, 'test'])
69
+ res = if query_or_body == :body
70
+ conn.public_send(http_method, '/', 'test')
71
+ else
72
+ conn.public_send(http_method, '/') do |req|
73
+ req.body = 'test'
74
+ end
75
+ end
76
+ expect(res.env.request_body).to eq('test')
77
+ end
78
+ end
79
+
80
+ it 'sends url encoded parameters' do
81
+ payload = { name: 'zack' }
82
+ request_stub.with(Hash[query_or_body, payload])
83
+ res = conn.public_send(http_method, '/', payload)
84
+ if query_or_body == :query
85
+ expect(res.env.request_body).to be_nil
86
+ else
87
+ expect(res.env.request_body).to eq('name=zack')
88
+ end
89
+ end
90
+
91
+ it 'sends url encoded nested parameters' do
92
+ payload = { name: { first: 'zack' } }
93
+ request_stub.with(Hash[query_or_body, payload])
94
+ conn.public_send(http_method, '/', payload)
95
+ end
96
+
97
+ # TODO: This needs reimplementation: see https://github.com/lostisland/faraday/issues/718
98
+ # Should raise Faraday::TimeoutError
99
+ it 'supports timeout option' do
100
+ conn_options[:request] = { timeout: 1 }
101
+ request_stub.to_timeout
102
+ exc = adapter == 'NetHttp' ? Faraday::ConnectionFailed : Faraday::TimeoutError
103
+ expect { conn.public_send(http_method, '/') }.to raise_error(exc)
104
+ end
105
+
106
+ # TODO: This needs reimplementation: see https://github.com/lostisland/faraday/issues/718
107
+ # Should raise Faraday::ConnectionFailed
108
+ it 'supports open_timeout option' do
109
+ conn_options[:request] = { open_timeout: 1 }
110
+ request_stub.to_timeout
111
+ exc = adapter == 'NetHttp' ? Faraday::ConnectionFailed : Faraday::TimeoutError
112
+ expect { conn.public_send(http_method, '/') }.to raise_error(exc)
113
+ end
114
+
115
+ # Can't send files on get, head and delete methods
116
+ if method_with_body?(http_method)
117
+ it 'sends files' do
118
+ payload = { uploaded_file: multipart_file }
119
+ request_stub.with(headers: { 'Content-Type' => %r{\Amultipart/form-data} }) do |request|
120
+ # WebMock does not support matching body for multipart/form-data requests yet :(
121
+ # https://github.com/bblimke/webmock/issues/623
122
+ request.body =~ /RubyMultipartPost/
123
+ end
124
+ conn.public_send(http_method, '/', payload)
125
+ end
126
+ end
127
+
128
+ on_feature :reason_phrase_parse do
129
+ it 'parses the reason phrase' do
130
+ request_stub.to_return(status: [200, 'OK'])
131
+ expect(response.reason_phrase).to eq('OK')
132
+ end
133
+ end
134
+
135
+ on_feature :compression do
136
+ # Accept-Encoding header not sent for HEAD requests as body is not expected in the response.
137
+ unless http_method == :head
138
+ it 'handles gzip compression' do
139
+ request_stub.with(headers: { 'Accept-Encoding' => /\bgzip\b/ })
140
+ conn.public_send(http_method, '/')
141
+ end
142
+
143
+ it 'handles deflate compression' do
144
+ request_stub.with(headers: { 'Accept-Encoding' => /\bdeflate\b/ })
145
+ conn.public_send(http_method, '/')
146
+ end
147
+ end
148
+ end
149
+
150
+ on_feature :streaming do
151
+ describe 'streaming' do
152
+ let(:streamed) { [] }
153
+
154
+ context 'when response is empty' do
155
+ it do
156
+ conn.public_send(http_method, '/') do |req|
157
+ req.options.on_data = proc { |*args| streamed << args }
158
+ end
159
+
160
+ expect(streamed).to eq([['', 0]])
161
+ end
162
+ end
163
+
164
+ context 'when response contains big data' do
165
+ before { request_stub.to_return(body: big_string) }
166
+
167
+ it 'handles streaming' do
168
+ response = conn.public_send(http_method, '/') do |req|
169
+ req.options.on_data = proc { |*args| streamed << args }
170
+ end
171
+
172
+ expect(response.body).to eq('')
173
+ check_streaming_response(streamed, chunk_size: 16 * 1024)
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ on_feature :parallel do
180
+ context 'with parallel setup' do
181
+ before do
182
+ @resp1 = nil
183
+ @resp2 = nil
184
+ @payload1 = { a: '1' }
185
+ @payload2 = { b: '2' }
186
+
187
+ request_stub
188
+ .with(Hash[query_or_body, @payload1])
189
+ .to_return(body: @payload1.to_json)
190
+
191
+ stub_request(http_method, remote)
192
+ .with(Hash[query_or_body, @payload2])
193
+ .to_return(body: @payload2.to_json)
194
+
195
+ conn.in_parallel do
196
+ @resp1 = conn.public_send(http_method, '/', @payload1)
197
+ @resp2 = conn.public_send(http_method, '/', @payload2)
198
+
199
+ expect(conn.in_parallel?).to be_truthy
200
+ expect(@resp1.body).to be_nil
201
+ expect(@resp2.body).to be_nil
202
+ end
203
+
204
+ expect(conn.in_parallel?).to be_falsey
205
+ end
206
+
207
+ it 'handles parallel requests status' do
208
+ expect(@resp1&.status).to eq(200)
209
+ expect(@resp2&.status).to eq(200)
210
+ end
211
+
212
+ unless http_method == :head && feature?(:skip_response_body_on_head)
213
+ it 'handles parallel requests body' do
214
+ expect(@resp1&.body).to eq(@payload1.to_json)
215
+ expect(@resp2&.body).to eq(@payload2.to_json)
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ it 'handles requests with proxy' do
222
+ conn_options[:proxy] = 'http://google.co.uk'
223
+
224
+ res = conn.public_send(http_method, '/')
225
+ expect(res.status).to eq(200)
226
+ end
227
+
228
+ it 'handles proxy failures' do
229
+ conn_options[:proxy] = 'http://google.co.uk'
230
+ request_stub.to_return(status: 407)
231
+
232
+ expect { conn.public_send(http_method, '/') }.to raise_error(Faraday::ProxyAuthError)
233
+ end
234
+ end