webmock 3.7.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.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +34 -0
  4. data/.rspec-tm +2 -0
  5. data/.travis.yml +19 -0
  6. data/CHANGELOG.md +1698 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE +20 -0
  9. data/README.md +1125 -0
  10. data/Rakefile +28 -0
  11. data/lib/webmock.rb +59 -0
  12. data/lib/webmock/api.rb +109 -0
  13. data/lib/webmock/assertion_failure.rb +11 -0
  14. data/lib/webmock/callback_registry.rb +35 -0
  15. data/lib/webmock/config.rb +18 -0
  16. data/lib/webmock/cucumber.rb +10 -0
  17. data/lib/webmock/deprecation.rb +9 -0
  18. data/lib/webmock/errors.rb +17 -0
  19. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +214 -0
  20. data/lib/webmock/http_lib_adapters/curb_adapter.rb +347 -0
  21. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +228 -0
  22. data/lib/webmock/http_lib_adapters/excon_adapter.rb +162 -0
  23. data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
  24. data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
  25. data/lib/webmock/http_lib_adapters/http_rb/client.rb +14 -0
  26. data/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
  27. data/lib/webmock/http_lib_adapters/http_rb/response.rb +43 -0
  28. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
  29. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  30. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  31. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +242 -0
  32. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +130 -0
  33. data/lib/webmock/http_lib_adapters/net_http.rb +361 -0
  34. data/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
  35. data/lib/webmock/http_lib_adapters/patron_adapter.rb +130 -0
  36. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +174 -0
  37. data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  38. data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  39. data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  40. data/lib/webmock/matchers/hash_including_matcher.rb +17 -0
  41. data/lib/webmock/minitest.rb +41 -0
  42. data/lib/webmock/rack_response.rb +69 -0
  43. data/lib/webmock/request_body_diff.rb +64 -0
  44. data/lib/webmock/request_execution_verifier.rb +77 -0
  45. data/lib/webmock/request_pattern.rb +370 -0
  46. data/lib/webmock/request_registry.rb +35 -0
  47. data/lib/webmock/request_signature.rb +54 -0
  48. data/lib/webmock/request_signature_snippet.rb +61 -0
  49. data/lib/webmock/request_stub.rb +100 -0
  50. data/lib/webmock/response.rb +153 -0
  51. data/lib/webmock/responses_sequence.rb +40 -0
  52. data/lib/webmock/rspec.rb +41 -0
  53. data/lib/webmock/rspec/matchers.rb +27 -0
  54. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +78 -0
  55. data/lib/webmock/rspec/matchers/webmock_matcher.rb +67 -0
  56. data/lib/webmock/stub_registry.rb +67 -0
  57. data/lib/webmock/stub_request_snippet.rb +38 -0
  58. data/lib/webmock/test_unit.rb +22 -0
  59. data/lib/webmock/util/hash_counter.rb +39 -0
  60. data/lib/webmock/util/hash_keys_stringifier.rb +25 -0
  61. data/lib/webmock/util/hash_validator.rb +17 -0
  62. data/lib/webmock/util/headers.rb +64 -0
  63. data/lib/webmock/util/json.rb +67 -0
  64. data/lib/webmock/util/query_mapper.rb +281 -0
  65. data/lib/webmock/util/uri.rb +110 -0
  66. data/lib/webmock/util/values_stringifier.rb +20 -0
  67. data/lib/webmock/util/version_checker.rb +111 -0
  68. data/lib/webmock/version.rb +3 -0
  69. data/lib/webmock/webmock.rb +161 -0
  70. data/minitest/test_helper.rb +34 -0
  71. data/minitest/test_webmock.rb +9 -0
  72. data/minitest/webmock_spec.rb +60 -0
  73. data/spec/acceptance/async_http_client/async_http_client_spec.rb +349 -0
  74. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  75. data/spec/acceptance/curb/curb_spec.rb +492 -0
  76. data/spec/acceptance/curb/curb_spec_helper.rb +147 -0
  77. data/spec/acceptance/em_http_request/em_http_request_spec.rb +406 -0
  78. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +77 -0
  79. data/spec/acceptance/excon/excon_spec.rb +77 -0
  80. data/spec/acceptance/excon/excon_spec_helper.rb +50 -0
  81. data/spec/acceptance/http_rb/http_rb_spec.rb +82 -0
  82. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
  83. data/spec/acceptance/httpclient/httpclient_spec.rb +217 -0
  84. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +57 -0
  85. data/spec/acceptance/manticore/manticore_spec.rb +56 -0
  86. data/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  87. data/spec/acceptance/net_http/net_http_shared.rb +153 -0
  88. data/spec/acceptance/net_http/net_http_spec.rb +331 -0
  89. data/spec/acceptance/net_http/net_http_spec_helper.rb +64 -0
  90. data/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
  91. data/spec/acceptance/patron/patron_spec.rb +125 -0
  92. data/spec/acceptance/patron/patron_spec_helper.rb +54 -0
  93. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +313 -0
  94. data/spec/acceptance/shared/callbacks.rb +148 -0
  95. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
  96. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
  97. data/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
  98. data/spec/acceptance/shared/request_expectations.rb +930 -0
  99. data/spec/acceptance/shared/returning_declared_responses.rb +409 -0
  100. data/spec/acceptance/shared/stubbing_requests.rb +643 -0
  101. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +135 -0
  102. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +60 -0
  103. data/spec/acceptance/webmock_shared.rb +41 -0
  104. data/spec/fixtures/test.txt +1 -0
  105. data/spec/quality_spec.rb +84 -0
  106. data/spec/spec_helper.rb +48 -0
  107. data/spec/support/example_curl_output.txt +22 -0
  108. data/spec/support/failures.rb +9 -0
  109. data/spec/support/my_rack_app.rb +53 -0
  110. data/spec/support/network_connection.rb +19 -0
  111. data/spec/support/webmock_server.rb +70 -0
  112. data/spec/unit/api_spec.rb +175 -0
  113. data/spec/unit/errors_spec.rb +129 -0
  114. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
  115. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
  116. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  117. data/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  118. data/spec/unit/rack_response_spec.rb +112 -0
  119. data/spec/unit/request_body_diff_spec.rb +90 -0
  120. data/spec/unit/request_execution_verifier_spec.rb +208 -0
  121. data/spec/unit/request_pattern_spec.rb +601 -0
  122. data/spec/unit/request_registry_spec.rb +95 -0
  123. data/spec/unit/request_signature_snippet_spec.rb +89 -0
  124. data/spec/unit/request_signature_spec.rb +155 -0
  125. data/spec/unit/request_stub_spec.rb +199 -0
  126. data/spec/unit/response_spec.rb +282 -0
  127. data/spec/unit/stub_registry_spec.rb +103 -0
  128. data/spec/unit/stub_request_snippet_spec.rb +115 -0
  129. data/spec/unit/util/hash_counter_spec.rb +39 -0
  130. data/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
  131. data/spec/unit/util/headers_spec.rb +28 -0
  132. data/spec/unit/util/json_spec.rb +33 -0
  133. data/spec/unit/util/query_mapper_spec.rb +157 -0
  134. data/spec/unit/util/uri_spec.rb +361 -0
  135. data/spec/unit/util/version_checker_spec.rb +65 -0
  136. data/spec/unit/webmock_spec.rb +19 -0
  137. data/test/http_request.rb +24 -0
  138. data/test/shared_test.rb +108 -0
  139. data/test/test_helper.rb +23 -0
  140. data/test/test_webmock.rb +6 -0
  141. data/webmock.gemspec +45 -0
  142. metadata +496 -0
@@ -0,0 +1,77 @@
1
+ module EMHttpRequestSpecHelper
2
+
3
+ def failed
4
+ EventMachine.stop
5
+ fail
6
+ end
7
+
8
+ def http_request(method, uri, options = {}, &block)
9
+ @http = nil
10
+ head = options[:headers] || {}
11
+ if options[:basic_auth]
12
+ head.merge!('authorization' => options[:basic_auth])
13
+ end
14
+ response = nil
15
+ error = nil
16
+ error_set = false
17
+ uri = Addressable::URI.heuristic_parse(uri)
18
+ EventMachine.run {
19
+ request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}")
20
+ http = request.send(method, {
21
+ timeout: 30,
22
+ body: options[:body],
23
+ file: options[:file],
24
+ query: options[:query],
25
+ head: head,
26
+ compressed: false
27
+ }, &block)
28
+ http.errback {
29
+ error_set = true
30
+ error = if http.respond_to?(:errors)
31
+ http.errors
32
+ else
33
+ http.error
34
+ end
35
+ failed
36
+ }
37
+ http.callback {
38
+ response = OpenStruct.new({
39
+ body: http.response,
40
+ headers: WebMock::Util::Headers.normalize_headers(extract_response_headers(http)),
41
+ message: http.response_header.http_reason,
42
+ status: http.response_header.status.to_s
43
+ })
44
+ EventMachine.stop
45
+ }
46
+ @http = http
47
+ }
48
+ raise error.to_s if error_set
49
+ response
50
+ end
51
+
52
+ def client_timeout_exception_class
53
+ "WebMock timeout error"
54
+ end
55
+
56
+ def connection_refused_exception_class
57
+ RuntimeError
58
+ end
59
+
60
+ def http_library
61
+ :em_http_request
62
+ end
63
+
64
+ private
65
+
66
+ def extract_response_headers(http)
67
+ headers = {}
68
+ if http.response_header
69
+ http.response_header.each do |k,v|
70
+ v = v.join(", ") if v.is_a?(Array)
71
+ headers[k] = v
72
+ end
73
+ end
74
+ headers
75
+ end
76
+
77
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'acceptance/webmock_shared'
3
+ require 'acceptance/excon/excon_spec_helper'
4
+
5
+ describe "Excon" do
6
+ include ExconSpecHelper
7
+ include_context "with WebMock", :no_url_auth
8
+
9
+ it 'should allow Excon requests to use query hash paramters' do
10
+ stub_request(:get, "http://example.com/resource/?a=1&b=2").to_return(body: "abc")
11
+ expect(Excon.new('http://example.com').get(path: "resource/", query: {a: 1, b: 2}).body).to eq("abc")
12
+ end
13
+
14
+ it 'should support Excon :expects options' do
15
+ stub_request(:get, "http://example.com/").to_return(body: 'a')
16
+ expect { Excon.new('http://example.com').get(expects: 204) }.to raise_error(Excon::Errors::OK)
17
+ end
18
+
19
+ context "with response_block" do
20
+ it "should support excon response_block for real requests", net_connect: true do
21
+ a = []
22
+ WebMock.allow_net_connect!
23
+ r = Excon.new('http://httpstat.us/200', headers: { "Accept" => "*" }).
24
+ get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
25
+ expect(a).to eq(["2", "0", "0", " ", "O", "K"])
26
+ expect(r.body).to eq("")
27
+ end
28
+
29
+ it "should support excon response_block" do
30
+ a = []
31
+ stub_request(:get, "http://example.com/").to_return(body: "abc")
32
+ r = Excon.new('http://example.com').get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
33
+ expect(a).to eq(['a', 'b', 'c'])
34
+ expect(r.body).to eq("")
35
+ end
36
+
37
+ it "should invoke callbacks with response body even if a real request is made", net_connect: true do
38
+ a = []
39
+ WebMock.allow_net_connect!
40
+ response = nil
41
+ WebMock.after_request { |_, res|
42
+ response = res
43
+ }
44
+ r = Excon.new('http://httpstat.us/200', headers: { "Accept" => "*" }).
45
+ get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
46
+ expect(response.body).to eq("200 OK")
47
+ expect(a).to eq(["2", "0", "0", " ", "O", "K"])
48
+ expect(r.body).to eq("")
49
+ end
50
+ end
51
+
52
+ let(:file) { File.new(__FILE__) }
53
+ let(:file_contents) { File.read(__FILE__) }
54
+
55
+ it 'handles file uploads correctly' do
56
+ stub_request(:put, "http://example.com/upload").with(body: file_contents)
57
+
58
+ yielded_request_body = nil
59
+ WebMock.after_request do |req, res|
60
+ yielded_request_body = req.body
61
+ end
62
+
63
+ Excon.new("http://example.com").put(path: "upload", body: file)
64
+
65
+ expect(yielded_request_body).to eq(file_contents)
66
+ end
67
+
68
+ describe '.request_params_from' do
69
+
70
+ it 'rejects invalid request keys' do
71
+ request_params = WebMock::HttpLibAdapters::ExconAdapter.request_params_from(body: :keep, fake: :reject)
72
+ expect(request_params).to eq(body: :keep)
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,50 @@
1
+ require 'ostruct'
2
+
3
+ module ExconSpecHelper
4
+
5
+ def http_request(method, uri, options = {}, &block)
6
+ Excon.defaults[:ssl_verify_peer] = false
7
+ Excon.defaults[:ciphers] = 'DEFAULT'
8
+ uri = Addressable::URI.heuristic_parse(uri)
9
+ uri = uri.to_s.gsub(' ', '%20')
10
+
11
+ excon_options = {}
12
+
13
+ if basic_auth = options.delete(:basic_auth)
14
+ excon_options = {user: basic_auth[0], password: basic_auth[1]}
15
+ end
16
+
17
+ if Gem::Version.new(Excon::VERSION) < Gem::Version.new("0.29.0")
18
+ options = options.merge(method: method, nonblock: false) # Dup and merge
19
+ response = Excon.new(uri, excon_options).request(options, &block)
20
+ else
21
+ options = options.merge(method: method) # Dup and merge
22
+ response = Excon.new(uri, excon_options.merge(nonblock: false)).request(options, &block)
23
+ end
24
+
25
+ headers = WebMock::Util::Headers.normalize_headers(response.headers)
26
+ headers = headers.inject({}) do |res, (name, value)|
27
+ res[name] = value.is_a?(Array) ? value.flatten.join(', ') : value
28
+ res
29
+ end
30
+
31
+ OpenStruct.new \
32
+ body: response.body,
33
+ headers: headers,
34
+ status: response.status.to_s,
35
+ message: response.reason_phrase
36
+ end
37
+
38
+ def client_timeout_exception_class
39
+ Excon::Errors::Timeout
40
+ end
41
+
42
+ def connection_refused_exception_class
43
+ Excon::Errors::SocketError
44
+ end
45
+
46
+ def http_library
47
+ :excon
48
+ end
49
+
50
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+ require "acceptance/webmock_shared"
5
+ require "acceptance/http_rb/http_rb_spec_helper"
6
+
7
+ describe "HTTP.rb" do
8
+ include HttpRbSpecHelper
9
+
10
+ include_examples "with WebMock", :no_status_message
11
+
12
+ context "streaming body" do
13
+ let(:response) { HTTP.get "http://example.com" }
14
+ before { stub_simple_request "example.com", 302, {}, "abc" }
15
+
16
+ it "works as if it was streamed from socket" do
17
+ expect(response.body.readpartial 1).to eq "a"
18
+ end
19
+
20
+ it "fails if body was already streamed" do
21
+ response.body.to_s
22
+ expect { response.body.readpartial 1 }.to raise_error(HTTP::StateError)
23
+ end
24
+ end
25
+
26
+ context "without following redirects" do
27
+ let(:response) { http_request(:get, "http://example.com") }
28
+ let(:headers) { response.headers }
29
+
30
+ it "stops on first request" do
31
+ stub_simple_request("example.com", 302, "Location" => "http://www.example.com")
32
+ stub_simple_request("www.example.com")
33
+
34
+ expect(headers).to include "Host" => "example.com"
35
+ end
36
+ end
37
+
38
+ context "following redirects" do
39
+ let(:options) { { follow: true } }
40
+ let(:response) { http_request(:get, "http://example.com", options) }
41
+ let(:headers) { response.headers }
42
+
43
+ it "returns response of destination" do
44
+ stub_simple_request("example.com", 302, "Location" => "http://www.example.com")
45
+ stub_simple_request("www.example.com")
46
+
47
+ expect(headers).to include "Host" => "www.example.com"
48
+ end
49
+ end
50
+
51
+ context "restored request uri on replayed response object" do
52
+ it "keeps non-default port" do
53
+ stub_request :get, "example.com:1234/foo"
54
+ response = HTTP.get "http://example.com:1234/foo"
55
+
56
+ expect(response.uri.to_s).to eq "http://example.com:1234/foo"
57
+ end
58
+
59
+ it "does not injects default port" do
60
+ stub_request :get, "example.com/foo"
61
+ response = HTTP.get "http://example.com/foo"
62
+
63
+ expect(response.uri.to_s).to eq "http://example.com/foo"
64
+ end
65
+
66
+ it "strips out default port even if it was explicitly given" do
67
+ stub_request :get, "example.com/foo"
68
+ response = HTTP.get "http://example.com:80/foo"
69
+
70
+ expect(response.uri.to_s).to eq "http://example.com/foo"
71
+ end
72
+ end
73
+
74
+ context "streamer" do
75
+ it "can be closed" do
76
+ stub_request :get, "example.com/foo"
77
+ response = HTTP.get "http://example.com/foo"
78
+
79
+ response.connection.close
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,54 @@
1
+ require "ostruct"
2
+
3
+ module HttpRbSpecHelper
4
+ def http_request(method, uri, options = {})
5
+ chain = HTTP
6
+
7
+ if basic_auth = options.delete(:basic_auth)
8
+ chain = chain.basic_auth(user: basic_auth[0], pass: basic_auth[1])
9
+ end
10
+
11
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
12
+ ssl_ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
13
+
14
+ response = chain.request(method, normalize_uri(uri), options.merge(ssl_context: ssl_ctx))
15
+
16
+ OpenStruct.new({
17
+ body: response.body.to_s,
18
+ headers: normalize_headers(response.headers.to_h),
19
+ status: response.code.to_s,
20
+ message: response.reason
21
+ })
22
+ end
23
+
24
+ def client_timeout_exception_class
25
+ return Errno::ETIMEDOUT if HTTP::VERSION < "1.0.0"
26
+ HTTP::TimeoutError
27
+ end
28
+
29
+ def connection_refused_exception_class
30
+ return Errno::ECONNREFUSED if HTTP::VERSION < "1.0.0"
31
+ HTTP::ConnectionError
32
+ end
33
+
34
+ def http_library
35
+ :http_rb
36
+ end
37
+
38
+ def normalize_uri(uri)
39
+ Addressable::URI.heuristic_parse(uri).normalize.to_s
40
+ end
41
+
42
+ def normalize_headers(headers)
43
+ headers = Hash[headers.map { |k, v| [k, Array(v).join(", ")] }]
44
+ WebMock::Util::Headers.normalize_headers headers
45
+ end
46
+
47
+ def stub_simple_request(host, status = 200, headers = {}, body = nil)
48
+ stub_request(:any, host).to_return({
49
+ status: status,
50
+ headers: headers.merge({ "Host" => host }),
51
+ body: body
52
+ })
53
+ end
54
+ end
@@ -0,0 +1,217 @@
1
+ require 'spec_helper'
2
+ require 'acceptance/webmock_shared'
3
+ require 'ostruct'
4
+
5
+ require 'acceptance/httpclient/httpclient_spec_helper'
6
+
7
+ describe "HTTPClient" do
8
+ include HTTPClientSpecHelper
9
+
10
+ before(:each) do
11
+ WebMock.reset_callbacks
12
+ HTTPClientSpecHelper.async_mode = false
13
+ end
14
+
15
+ include_examples "with WebMock"
16
+
17
+ it "should raise a clearly readable error if request with multipart body is sent" do
18
+ stub_request(:post, 'www.example.com').with(body: {type: 'image'})
19
+
20
+ expect {
21
+ HTTPClient.new.post_content('www.example.com', type: 'image', file: File.new('spec/fixtures/test.txt'))
22
+ }.to raise_error(ArgumentError, "WebMock does not support matching body for multipart/form-data requests yet :(")
23
+ end
24
+
25
+ it "should yield block on response if block provided" do
26
+ stub_request(:get, "www.example.com").to_return(body: "abc")
27
+ response_body = ""
28
+ http_request(:get, "http://www.example.com/") do |body|
29
+ response_body = body
30
+ end
31
+ expect(response_body).to eq("abc")
32
+ end
33
+
34
+ it "should not yield block on empty response if block provided" do
35
+ stub_request(:get, "www.example.com").to_return(body: "")
36
+ response_body = ""
37
+ http_request(:get, "http://www.example.com/"){ raise }
38
+ expect(response_body).to eq("")
39
+ end
40
+
41
+ it "should match requests if headers are the same but in different order" do
42
+ stub_request(:get, "www.example.com").with(headers: {"a" => ["b", "c"]} )
43
+ expect(http_request(
44
+ :get, "http://www.example.com/",
45
+ headers: {"a" => ["c", "b"]}).status).to eq("200")
46
+ end
47
+
48
+ describe "when using async requests" do
49
+ before(:each) do
50
+ HTTPClientSpecHelper.async_mode = true
51
+ end
52
+
53
+ include_examples "with WebMock"
54
+ end
55
+
56
+ it "should work with get_content" do
57
+ stub_request(:get, 'www.example.com').to_return(status: 200, body: 'test', headers: {})
58
+ str = ''.dup
59
+ HTTPClient.get_content('www.example.com') do |content|
60
+ str << content
61
+ end
62
+ expect(str).to eq('test')
63
+ end
64
+
65
+ it "should work via JSONClient subclass" do
66
+ stub_request(:get, 'www.example.com').to_return(
67
+ status: 200,
68
+ body: '{"test": "foo"}',
69
+ headers: {'Content-Type' => 'application/json'}
70
+ )
71
+ content = JSONClient.get('www.example.com').content
72
+ expect(content).to eq("test" => "foo")
73
+ end
74
+
75
+ context "multipart bodies" do
76
+ let(:header) {{
77
+ 'Accept' => 'application/json',
78
+ 'Content-Type' => 'multipart/form-data'
79
+ }}
80
+
81
+ let(:body) {[
82
+ {
83
+ 'Content-Type' => 'application/json',
84
+ 'Content-Disposition' => 'form-data',
85
+ :content => '{"foo": "bar", "baz": 2}'
86
+ }
87
+ ]}
88
+
89
+ let(:make_request) {HTTPClient.new.post("http://www.example.com", body: body, header: header)}
90
+
91
+ before do
92
+ stub_request(:post, "www.example.com")
93
+ end
94
+
95
+ it "should work with multipart bodies" do
96
+ make_request
97
+ end
98
+ end
99
+
100
+
101
+ context "Filters" do
102
+ class Filter
103
+ def filter_request(request)
104
+ request.header["Authorization"] = "Bearer 0123456789"
105
+ end
106
+
107
+ def filter_response(request, response)
108
+ response.header.set('X-Powered-By', 'webmock')
109
+ end
110
+ end
111
+
112
+ before do
113
+ @client = HTTPClient.new
114
+ @client.request_filter << Filter.new
115
+ stub_request(:get, 'www.example.com').with(headers: {'Authorization' => 'Bearer 0123456789'})
116
+ end
117
+
118
+ it "supports request filters" do
119
+ expect(@client.request(:get, 'http://www.example.com/').status).to eq(200)
120
+ end
121
+
122
+ it "supports response filters" do
123
+ res = @client.request(:get, 'http://www.example.com/')
124
+ expect(res.header['X-Powered-By'].first).to eq('webmock')
125
+ end
126
+ end
127
+
128
+ context 'when a client instance is re-used for another identical request' do
129
+ let(:client) { HTTPClient.new }
130
+ let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"}
131
+
132
+ before { WebMock.allow_net_connect! }
133
+
134
+ it 'invokes the global_stub_request hook for each request' do
135
+ # Mock time to ensure that date headers match
136
+ now = Time.now
137
+ allow(Time).to receive(:now).and_return(now)
138
+
139
+ request_signatures = []
140
+ WebMock.globally_stub_request do |request_sig|
141
+ request_signatures << request_sig
142
+ nil # to let the request be made for real
143
+ end
144
+
145
+ http_request(:get, webmock_server_url, client: client, headers: { "Cookie" => "bar=; foo=" })
146
+
147
+ if defined? HTTP::CookieJar
148
+ http_request(:get, webmock_server_url, client: client, headers: { "Cookie" => "bar=; foo=" })
149
+ else
150
+ # If http-cookie is not present, then the cookie headers will saved between requests
151
+ http_request(:get, webmock_server_url, client: client)
152
+ end
153
+
154
+ expect(request_signatures.size).to eq(2)
155
+ # Verify the request signatures were identical as needed by this example
156
+ expect(request_signatures.first).to eq(request_signatures.last)
157
+ end
158
+ end
159
+
160
+ context 'session headers' do
161
+ it "client sends a User-Agent header when given an agent_name explicitly to the client" do
162
+ user_agent = "Client/0.1"
163
+ stub_request(:get, "www.example.com").with(headers: { 'User-agent' => "#{user_agent} #{HTTPClient::LIB_NAME}" })
164
+ HTTPClient.new(agent_name: user_agent).get("www.example.com")
165
+ end
166
+
167
+ it "client sends the Accept, User-Agent, and Date by default" do
168
+ WebMock.disable_net_connect!
169
+ stub_request(:get, "www.example.com").with do |req|
170
+ req.headers["Accept"] == "*/*" &&
171
+ req.headers["User-Agent"] == "#{HTTPClient::DEFAULT_AGENT_NAME} #{HTTPClient::LIB_NAME}" &&
172
+ req.headers["Date"]
173
+ end
174
+ http_request(:get, "www.example.com")
175
+ end
176
+
177
+ it "explicitly defined headers take precedence over session defaults" do
178
+ headers = { 'Accept' => 'foo/bar', 'User-Agent' => 'custom', 'Date' => 'today' }
179
+ stub_request(:get, "www.example.com").with(headers: headers)
180
+ HTTPClient.new.get("www.example.com", nil, headers)
181
+ end
182
+ end
183
+
184
+ context 'httpclient response header' do
185
+ it 'receives request_method, request_uri, and request_query from the request header' do
186
+ stub_request :get, 'www.example.com'
187
+ message = HTTPClient.new.get 'www.example.com'
188
+ expect(message.header.request_uri.to_s).to eq('www.example.com')
189
+ end
190
+ end
191
+
192
+ context 'httpclient streams response', net_connect: true do
193
+ before do
194
+ WebMock.allow_net_connect!
195
+ WebMock.after_request(except: [:other_lib]) do |_, response|
196
+ @response = response
197
+ end
198
+ end
199
+
200
+ it 'sets the full body on the webmock response' do
201
+ body = ''
202
+ HTTPClient.new.request(:get, 'http://www.example.com/') do |http_res, chunk|
203
+ body += chunk
204
+ end
205
+ expect(@response.body).to eq body
206
+ end
207
+ end
208
+
209
+ context 'credentials' do
210
+ it 'are detected when manually specifying Authorization header' do
211
+ stub_request(:get, "http://www.example.com/").with(basic_auth: ['username', 'password']).to_return(status: 200)
212
+
213
+ headers = {'Authorization' => 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='}
214
+ expect(http_request(:get, 'http://www.example.com/', {headers: headers}).status).to eql('200')
215
+ end
216
+ end
217
+ end