excon 0.64.0 → 0.65.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of excon might be problematic. Click here for more details.

Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/data/cacert.pem +108 -2
  3. data/excon.gemspec +7 -2
  4. data/lib/excon.rb +11 -11
  5. data/lib/excon/connection.rb +25 -25
  6. data/lib/excon/response.rb +1 -1
  7. data/lib/excon/version.rb +1 -1
  8. metadata +3 -101
  9. data/.document +0 -5
  10. data/.github/stale.yml +0 -17
  11. data/.gitignore +0 -13
  12. data/.rspec +0 -3
  13. data/.travis.yml +0 -17
  14. data/Gemfile +0 -19
  15. data/Rakefile +0 -41
  16. data/benchmarks/class_vs_lambda.rb +0 -50
  17. data/benchmarks/concat_vs_insert.rb +0 -21
  18. data/benchmarks/concat_vs_interpolate.rb +0 -22
  19. data/benchmarks/cr_lf.rb +0 -21
  20. data/benchmarks/downcase-eq-eq_vs_casecmp.rb +0 -169
  21. data/benchmarks/excon.rb +0 -69
  22. data/benchmarks/excon_vs.rb +0 -165
  23. data/benchmarks/for_vs_array_each.rb +0 -27
  24. data/benchmarks/for_vs_hash_each.rb +0 -27
  25. data/benchmarks/has_key-vs-lookup.rb +0 -177
  26. data/benchmarks/headers_case_sensitivity.rb +0 -83
  27. data/benchmarks/headers_split_vs_match.rb +0 -34
  28. data/benchmarks/implicit_block-vs-explicit_block.rb +0 -98
  29. data/benchmarks/merging.rb +0 -21
  30. data/benchmarks/single_vs_double_quotes.rb +0 -21
  31. data/benchmarks/string_ranged_index.rb +0 -87
  32. data/benchmarks/strip_newline.rb +0 -115
  33. data/benchmarks/vs_stdlib.rb +0 -82
  34. data/changelog.txt +0 -1113
  35. data/spec/excon/error_spec.rb +0 -139
  36. data/spec/excon/test/server_spec.rb +0 -28
  37. data/spec/excon_spec.rb +0 -7
  38. data/spec/helpers/file_path_helpers.rb +0 -22
  39. data/spec/helpers/warning_helpers.rb +0 -9
  40. data/spec/requests/basic_spec.rb +0 -40
  41. data/spec/requests/eof_requests_spec.rb +0 -36
  42. data/spec/requests/unix_socket_spec.rb +0 -38
  43. data/spec/requests/validation_spec.rb +0 -80
  44. data/spec/spec_helper.rb +0 -26
  45. data/spec/support/shared_contexts/test_server_context.rb +0 -83
  46. data/spec/support/shared_contexts/test_stub_context.rb +0 -11
  47. data/spec/support/shared_examples/shared_example_for_clients.rb +0 -220
  48. data/spec/support/shared_examples/shared_example_for_streaming_clients.rb +0 -20
  49. data/spec/support/shared_examples/shared_example_for_test_servers.rb +0 -16
  50. data/tests/authorization_header_tests.rb +0 -27
  51. data/tests/bad_tests.rb +0 -69
  52. data/tests/basic_tests.rb +0 -351
  53. data/tests/batch_requests.rb +0 -133
  54. data/tests/complete_responses.rb +0 -31
  55. data/tests/data/127.0.0.1.cert.crt +0 -17
  56. data/tests/data/127.0.0.1.cert.key +0 -28
  57. data/tests/data/excon.cert.crt +0 -17
  58. data/tests/data/excon.cert.key +0 -28
  59. data/tests/data/xs +0 -1
  60. data/tests/error_tests.rb +0 -145
  61. data/tests/header_tests.rb +0 -119
  62. data/tests/instrumentors/logging_instrumentor_tests.rb +0 -28
  63. data/tests/middleware_tests.rb +0 -27
  64. data/tests/middlewares/canned_response_tests.rb +0 -34
  65. data/tests/middlewares/capture_cookies_tests.rb +0 -34
  66. data/tests/middlewares/decompress_tests.rb +0 -157
  67. data/tests/middlewares/escape_path_tests.rb +0 -36
  68. data/tests/middlewares/idempotent_tests.rb +0 -245
  69. data/tests/middlewares/instrumentation_tests.rb +0 -315
  70. data/tests/middlewares/mock_tests.rb +0 -304
  71. data/tests/middlewares/redirect_follower_tests.rb +0 -112
  72. data/tests/pipeline_tests.rb +0 -40
  73. data/tests/proxy_tests.rb +0 -306
  74. data/tests/query_string_tests.rb +0 -87
  75. data/tests/rackups/basic.rb +0 -41
  76. data/tests/rackups/basic.ru +0 -3
  77. data/tests/rackups/basic_auth.ru +0 -14
  78. data/tests/rackups/deflater.ru +0 -4
  79. data/tests/rackups/proxy.ru +0 -18
  80. data/tests/rackups/query_string.ru +0 -13
  81. data/tests/rackups/redirecting.ru +0 -23
  82. data/tests/rackups/redirecting_with_cookie.ru +0 -40
  83. data/tests/rackups/request_headers.ru +0 -15
  84. data/tests/rackups/request_methods.ru +0 -21
  85. data/tests/rackups/response_header.ru +0 -18
  86. data/tests/rackups/ssl.ru +0 -16
  87. data/tests/rackups/ssl_mismatched_cn.ru +0 -15
  88. data/tests/rackups/ssl_verify_peer.ru +0 -16
  89. data/tests/rackups/streaming.ru +0 -30
  90. data/tests/rackups/thread_safety.ru +0 -17
  91. data/tests/rackups/timeout.ru +0 -14
  92. data/tests/rackups/webrick_patch.rb +0 -34
  93. data/tests/request_headers_tests.rb +0 -21
  94. data/tests/request_method_tests.rb +0 -47
  95. data/tests/request_tests.rb +0 -58
  96. data/tests/response_tests.rb +0 -197
  97. data/tests/servers/bad.rb +0 -25
  98. data/tests/servers/eof.rb +0 -17
  99. data/tests/servers/error.rb +0 -20
  100. data/tests/servers/good.rb +0 -342
  101. data/tests/servers/good_ipv4.rb +0 -8
  102. data/tests/servers/good_ipv6.rb +0 -8
  103. data/tests/test_helper.rb +0 -297
  104. data/tests/thread_safety_tests.rb +0 -39
  105. data/tests/timeout_tests.rb +0 -12
  106. data/tests/utils_tests.rb +0 -81
@@ -1,11 +0,0 @@
1
- shared_context "stubs" do
2
- before do
3
- @original_mock = Excon.defaults[:mock]
4
- Excon.defaults[:mock] = true
5
- end
6
-
7
- after do
8
- Excon.defaults[:mock] = @original_mock
9
- Excon.stubs.clear
10
- end
11
- end
@@ -1,220 +0,0 @@
1
- require 'time'
2
-
3
- shared_examples_for 'a basic client' do |url = 'http://127.0.0.1:9292', opts = {}|
4
- # TODO: Ditch iterator and manually write a context for each set of options
5
- ([true, false] * 2).combination(2).to_a.uniq.each do |nonblock, persistent|
6
- context "when nonblock is #{nonblock} and persistent is #{persistent}" do
7
- opts = opts.merge(ssl_verify_peer: false, nonblock: nonblock, persistent: persistent)
8
-
9
- let(:conn) { Excon.new(url, opts) }
10
-
11
- context 'when :method is get and :path is /content-length/100' do
12
- describe '#request' do
13
- let(:response) do
14
- conn.request(method: :get, path: '/content-length/100')
15
- end
16
-
17
- it 'returns an Excon::Response' do
18
- expect(response).to be_instance_of Excon::Response
19
- end
20
- describe Excon::Response do
21
- describe '#status' do
22
- it 'returns 200' do
23
- expect(response.status).to eq 200
24
- end
25
-
26
- it '#status returns 200' do
27
- expect(response[:status]).to eq 200
28
- end
29
- end
30
- describe '#headers' do
31
- it '["Content-Length"] returns 100' do
32
- expect(response.headers['Content-Length']).to eq '100'
33
- end
34
- it '["Content-Type"] returns "text/html;charset=utf-8"' do
35
- expect(response.headers['Content-Type']).to eq 'text/html;charset=utf-8'
36
- end
37
-
38
- it "['Date'] returns a valid date" do
39
- if RUBY_PLATFORM == 'java' && conn.data[:scheme] == Excon::UNIX
40
- skip('until puma responds with a date header')
41
- else
42
- time = Time.parse(response.headers['Date'])
43
- expect(time.is_a?(Time)).to be true
44
- end
45
- end
46
-
47
- it "['Server'] matches /^WEBrick/" do
48
- pending('until unix_socket response has server header') if conn.data[:scheme] == Excon::UNIX
49
- expect(!!(response.headers['Server'] =~ /^WEBrick/)).to be true
50
- end
51
-
52
- it "['Custom'] returns Foo: bar" do
53
- expect(response.headers['Custom']).to eq 'Foo: bar'
54
- end
55
- end
56
- describe '#remote_ip' do
57
- it 'returns 127.0.0.1' do
58
- pending('until pigs can fly') if conn.data[:scheme] == Excon::UNIX
59
- expect(response.remote_ip).to eq '127.0.0.1'
60
- end
61
- end
62
- end
63
-
64
- context('when tcp_nodelay is true') do
65
- describe '#request' do
66
- response = nil
67
- options = opts.merge(ssl_verify_peer: false, nonblock: nonblock, tcp_nodelay: true)
68
- connection = Excon.new(url, options)
69
-
70
- it 'returns an Excon::Response' do
71
- expect do
72
- response = connection.request(method: :get, path: '/content-length/100')
73
- end.to_not raise_error
74
- end
75
-
76
- describe Excon::Response do
77
- describe '#body' do
78
- describe '.status' do
79
- it '#returns 200' do
80
- expect(response.status).to eq 200
81
- end
82
- end
83
- end
84
- end
85
- end
86
- end
87
- end
88
-
89
- context 'when utilizing deprecated block usage' do
90
- describe '#request' do
91
- data = []
92
- it 'yields with a chunk, remaining length, and total length' do
93
- expect do
94
- silence_warnings do
95
- conn.request(method: :get, path: '/content-length/100') do |chunk, remaining_length, total_length|
96
- data = [chunk, remaining_length, total_length]
97
- end
98
- end
99
- end.to_not raise_error
100
- end
101
- it 'completes with expected data' do
102
- expect(data).to eq ['x' * 100, 0, 100]
103
- end
104
- end
105
- end
106
-
107
- context 'when utilizing response_block usage' do
108
- describe '#request' do
109
- data = []
110
- it 'yields a chunk, remaining length, and total_length' do
111
- response_block = lambda do |chunk, remaining_length, total_length|
112
- data = [chunk, remaining_length, total_length]
113
- end
114
- expect do
115
- conn.request(method: :get, path: '/content-length/100', response_block: response_block)
116
- end.to_not raise_error
117
- end
118
- it 'completes with expected data' do
119
- expect(data).to eq ['x' * 100, 0, 100]
120
- end
121
- end
122
- end
123
- context 'when method is :post' do
124
- context 'when :path is /body-sink' do
125
- context 'when a body parameter is supplied' do
126
- response = nil
127
- it 'returns an Excon::Response' do
128
- response = conn.request(method: :post, path: '/body-sink', headers: { 'Content-Type' => 'text/plain' }, body: 'x' * 5_000_000)
129
- expect(response).to be_instance_of Excon::Response
130
- end
131
- describe Excon::Response do
132
- describe '#body' do
133
- it 'equals "5000000"' do
134
- expect(response.body).to eq '5000000'
135
- end
136
- end
137
- end
138
- end
139
- context 'when the body parameter is an empty string' do
140
- response = nil
141
-
142
- it 'returns an Excon::Response' do
143
- response = conn.request(method: :post, path: '/body-sink', headers: { 'Content-Type' => 'text/plain' }, body: '')
144
- expect(response).to be_instance_of Excon::Response
145
- end
146
- describe Excon::Response do
147
- describe '#body' do
148
- it 'equals "0"' do
149
- expect(response.body).to eq '0'
150
- end
151
- end
152
- end
153
- end
154
- end
155
-
156
- context 'when :path is /echo' do
157
- context('when a file handle is the body paramter') do
158
- describe Excon::Response do
159
- it '#body equals "x" * 100 + "\n"' do
160
- file_path = data_path('xs')
161
- response = conn.request(method: :post, path: '/echo', body: File.open(file_path))
162
- expect(response.body).to eq 'x' * 100 + "\n"
163
- end
164
- end
165
- end
166
-
167
- context 'when a string is the body paramter' do
168
- it 'does not change the enconding of the body' do
169
- skip unless RUBY_VERSION >= '2.0'
170
-
171
- string_body = '¥£€'
172
- expect do
173
- conn.request(method: :post, path: '/echo', body: string_body)
174
- end.to_not change { string_body.encoding }
175
- end
176
-
177
- context 'without request_block' do
178
- describe Excon::Response do
179
- it "#body equals 'x' * 100)" do
180
- response = conn.request(method: :post, path: '/echo', body: 'x' * 100)
181
- expect(response.body).to eq 'x' * 100
182
- end
183
- end
184
- end
185
-
186
- context 'when a request_block paramter is supplied' do
187
- describe Excon::Response do
188
- it "#body equals'x' * 100" do
189
- data = ['x'] * 100
190
- request_block = lambda do
191
- data.shift.to_s
192
- end
193
- response = conn.request(method: :post, path: '/echo', request_block: request_block)
194
- expect(response.body).to eq 'x' * 100
195
- end
196
- end
197
- end
198
-
199
- context('when a multi-byte string is the body paramter') do
200
- body = "\xC3\xBC" * 100
201
- headers = { 'Custom' => body.dup }
202
- if RUBY_VERSION >= '1.9'
203
- body.force_encoding('BINARY')
204
- headers['Custom'].force_encoding('UTF-8')
205
- end
206
- describe Excon::Response do
207
- it '#body properly concatenates request+headers and body' do
208
- response = conn.request(method: :post, path: '/echo',
209
- headers: headers, body: body)
210
- expect(response.body).to eq body
211
- end
212
- end
213
- end
214
- end
215
- end
216
- end
217
- end
218
- end
219
- end
220
- end
@@ -1,20 +0,0 @@
1
- shared_examples_for 'a streaming client' do |endpoint, timeout|
2
- ret = []
3
- timing = 'response times ok'
4
- start = Time.now
5
- block = lambda do |c,r,t|
6
- # add the response
7
- ret.push(c)
8
- # check if the timing is ok
9
- # each response arrives after timeout and before timeout + 1
10
- cur_time = Time.now - start
11
- if cur_time < ret.length * timeout or cur_time > (ret.length+1) * timeout
12
- timing = 'response time not ok!'
13
- end
14
- end
15
- it "gets a response in less than or equal to #{(timeout*3).round(2)} seconds" do
16
- Excon.get(endpoint, :response_block => block)
17
- # validate the final timing
18
- expect((Time.now - start <= timeout*3) == true && timing == 'response times not ok!').to be false
19
- end
20
- end
@@ -1,16 +0,0 @@
1
- shared_examples_for "a excon test server" do |plugin, file|
2
-
3
- include_context("test server", plugin, file)
4
-
5
- it "returns an instance" do
6
- expect(@server).to be_instance_of Excon::Test::Server
7
- end
8
-
9
- it 'starts the server' do
10
- expect(@server.start).to be true
11
- end
12
-
13
- it 'stops the server' do
14
- expect(@server.stop).to be true
15
- end
16
- end
@@ -1,27 +0,0 @@
1
- Shindo.tests('Excon basics (Authorization data redacted)') do
2
- cases = [
3
- ['user & pass', 'http://user1:pass1@foo.com/', 'Basic dXNlcjE6cGFzczE='],
4
- ['email & pass', 'http://foo%40bar.com:pass1@foo.com/', 'Basic Zm9vQGJhci5jb206cGFzczE='],
5
- ['user no pass', 'http://three_user@foo.com/', 'Basic dGhyZWVfdXNlcjo='],
6
- ['pass no user', 'http://:derppass@foo.com/', 'Basic OmRlcnBwYXNz']
7
- ]
8
- cases.each do |desc,url,auth_header|
9
- conn = nil
10
-
11
- test("authorization header concealed for #{desc}") do
12
- conn = Excon.new(url)
13
- !conn.inspect.include?(auth_header)
14
- end
15
-
16
- if conn.data[:password]
17
- test("password param concealed for #{desc}") do
18
- !conn.inspect.include?(conn.data[:password])
19
- end
20
- end
21
-
22
- test("password param remains correct for #{desc}") do
23
- conn.data[:password] == URI.parse(url).password
24
- end
25
-
26
- end
27
- end
@@ -1,69 +0,0 @@
1
- Shindo.tests('Excon bad server interaction') do
2
-
3
- with_server('bad') do
4
-
5
- tests('header splitting') do
6
-
7
- tests('prevents key splitting').raises(Excon::Errors::InvalidHeaderKey) do
8
- connection = Excon.new('http://127.0.0.1:9292')
9
- connection.request(
10
- headers: { "Foo\r\nBar" => "baz" },
11
- method: :get,
12
- path: '/echo'
13
- )
14
- end
15
-
16
- tests('prevents value splitting').raises(Excon::Errors::InvalidHeaderValue) do
17
- connection = Excon.new('http://127.0.0.1:9292')
18
- connection.request(
19
- headers: { Foo: "bar\r\nBaz: qux" },
20
- method: :get,
21
- path: '/echo'
22
- )
23
- end
24
-
25
- end
26
-
27
- tests('bad server: causes EOFError') do
28
-
29
- tests('with no content length and no chunking') do
30
- tests('without a block') do
31
- tests('response.body').returns('hello') do
32
- connection = Excon.new('http://127.0.0.1:9292')
33
-
34
- connection.request(:method => :get, :path => '/eof/no_content_length_and_no_chunking').body
35
- end
36
- end
37
-
38
- tests('with a block') do
39
- tests('body from chunks').returns('hello') do
40
- connection = Excon.new('http://127.0.0.1:9292')
41
-
42
- body = ""
43
- response_block = lambda {|chunk, remaining, total| body << chunk }
44
-
45
- connection.request(:method => :get, :path => '/eof/no_content_length_and_no_chunking', :response_block => response_block)
46
-
47
- body
48
- end
49
- end
50
-
51
- end
52
-
53
- end
54
-
55
- end
56
-
57
- with_server('eof') do
58
-
59
- tests('eof server: causes EOFError') do
60
-
61
- tests('request').raises(Excon::Errors::SocketError) do
62
- Excon.get('http://127.0.0.1:9292/eof')
63
- end
64
-
65
- end
66
-
67
- end
68
-
69
- end
@@ -1,351 +0,0 @@
1
- require 'json'
2
-
3
- Shindo.tests('Excon basics') do
4
- env_init
5
-
6
- with_rackup('basic.ru') do
7
- basic_tests
8
-
9
- tests('explicit uri passed to connection') do
10
- tests('GET /content-length/100').returns(200) do
11
- connection = Excon::Connection.new({
12
- :host => '127.0.0.1',
13
- :hostname => '127.0.0.1',
14
- :nonblock => false,
15
- :port => 9292,
16
- :scheme => 'http',
17
- :ssl_verify_peer => false
18
- })
19
- response = connection.request(:method => :get, :path => '/content-length/100')
20
- response[:status]
21
- end
22
- end
23
- end
24
- end
25
-
26
- Shindo.tests('Excon streaming basics') do
27
- pending if RUBY_PLATFORM == 'java' # need to find suitable server for jruby
28
- with_unicorn('streaming.ru') do
29
- # expected values: the response, in pieces, and a timeout after each piece
30
- res = %w{Hello streamy world}
31
- timeout = 0.1
32
-
33
- # expect the full response as a string
34
- # and expect it to take a (timeout * pieces) seconds
35
- tests('simple blocking request on streaming endpoint').returns([res.join(''),'response time ok']) do
36
- start = Time.now
37
- ret = Excon.get('http://127.0.0.1:9292/streamed/simple').body
38
-
39
- if Time.now - start <= timeout*3
40
- [ret, 'streaming response came too quickly']
41
- else
42
- [ret, 'response time ok']
43
- end
44
- end
45
-
46
- # expect the full response as a string and expect it to
47
- # take a (timeout * pieces) seconds (with fixed Content-Length header)
48
- tests('simple blocking request on streaming endpoint with fixed length').returns([res.join(''),'response time ok']) do
49
- start = Time.now
50
- ret = Excon.get('http://127.0.0.1:9292/streamed/fixed_length').body
51
-
52
- if Time.now - start <= timeout*3
53
- [ret, 'streaming response came too quickly']
54
- else
55
- [ret, 'response time ok']
56
- end
57
- end
58
-
59
- # expect each response piece to arrive to the body right away
60
- # and wait for timeout until next one arrives
61
- def timed_streaming_test(endpoint, timeout)
62
- ret = []
63
- timing = 'response times ok'
64
- start = Time.now
65
- Excon.get(endpoint, :response_block => lambda do |c,r,t|
66
- # add the response
67
- ret.push(c)
68
- # check if the timing is ok
69
- # each response arrives after timeout and before timeout + 1
70
- cur_time = Time.now - start
71
- if cur_time < ret.length * timeout or cur_time > (ret.length+1) * timeout
72
- timing = 'response time not ok!'
73
- end
74
- end)
75
- # validate the final timing
76
- if Time.now - start <= timeout*3
77
- timing = 'final timing was not ok!'
78
- end
79
- [ret, timing]
80
- end
81
-
82
- tests('simple request with response_block on streaming endpoint').returns([res,'response times ok']) do
83
- timed_streaming_test('http://127.0.0.1:9292/streamed/simple', timeout)
84
- end
85
-
86
- tests('simple request with response_block on streaming endpoint with fixed length').returns([res,'response times ok']) do
87
- timed_streaming_test('http://127.0.0.1:9292/streamed/fixed_length', timeout)
88
- end
89
-
90
- end
91
- end
92
-
93
- Shindo.tests('Excon basics (Basic Auth Pass)') do
94
- with_rackup('basic_auth.ru') do
95
- basic_tests('http://test_user:test_password@127.0.0.1:9292')
96
- user, pass, uri = ['test_user', 'test_password', 'http://127.0.0.1:9292'].map(&:freeze)
97
-
98
- tests('with frozen args').returns(200) do
99
- connection = Excon.new(uri, :method => :get, :password => pass, :path => '/content-length/100', :user => user)
100
- response = connection.request
101
- response.status
102
- end
103
-
104
- tests('with user/pass on request').returns(200) do
105
- connection = Excon.new(uri, :method => :get, :path => '/content-length/100')
106
- response = connection.request(:user => user, :password => pass)
107
- response.status
108
- end
109
-
110
- tests('with user/pass on connection and request').returns(200) do
111
- connection = Excon.new(uri, :method => :get, :password => 'incorrect_password', :path => '/content-length/100', :user => 'incorrect_user')
112
- response = connection.request(user: user, password: pass)
113
- response.status
114
- end
115
- end
116
- end
117
-
118
- Shindo.tests('Excon basics (Basic Auth Fail)') do
119
- with_rackup('basic_auth.ru') do
120
- cases = [
121
- ['correct user, no password', 'http://test_user@127.0.0.1:9292'],
122
- ['correct user, wrong password', 'http://test_user:fake_password@127.0.0.1:9292'],
123
- ['wrong user, correct password', 'http://fake_user:test_password@127.0.0.1:9292']
124
- ]
125
- cases.each do |desc,url|
126
- tests("response.status for #{desc}").returns(401) do
127
- connection = Excon.new(url)
128
- response = connection.request(:method => :get, :path => '/content-length/100')
129
- response.status
130
- end
131
- end
132
- end
133
- end
134
-
135
- Shindo.tests('Excon basics (ssl)') do
136
- with_rackup('ssl.ru') do
137
- basic_tests('https://127.0.0.1:9443')
138
- end
139
- end
140
-
141
- Shindo.tests('Excon ssl verify peer (ssl)') do
142
- with_rackup('ssl.ru') do
143
- connection = nil
144
- test do
145
- ssl_ca_file = File.join(File.dirname(__FILE__), 'data', '127.0.0.1.cert.crt')
146
- connection = Excon.new('https://127.0.0.1:9443', :ssl_verify_peer => true, :ssl_ca_file => ssl_ca_file )
147
- true
148
- end
149
-
150
- tests('response.status').returns(200) do
151
- response = connection.request(:method => :get, :path => '/content-length/100')
152
-
153
- response.status
154
- end
155
- end
156
-
157
- with_rackup('ssl_mismatched_cn.ru') do
158
- connection = nil
159
- test do
160
- ssl_ca_file = File.join(File.dirname(__FILE__), 'data', 'excon.cert.crt')
161
- connection = Excon.new('https://127.0.0.1:9443', :ssl_verify_peer => true, :ssl_ca_file => ssl_ca_file, :ssl_verify_peer_host => 'excon' )
162
- true
163
- end
164
-
165
- tests('response.status').returns(200) do
166
- response = connection.request(:method => :get, :path => '/content-length/100')
167
-
168
- response.status
169
- end
170
- end
171
- end
172
-
173
- Shindo.tests('Excon ssl verify peer (ssl cert store)') do
174
- with_rackup('ssl.ru') do
175
- connection = nil
176
- test do
177
- ssl_ca_cert = File.read(File.join(File.dirname(__FILE__), 'data', '127.0.0.1.cert.crt'))
178
- ssl_cert_store = OpenSSL::X509::Store.new
179
- ssl_cert_store.add_cert OpenSSL::X509::Certificate.new ssl_ca_cert
180
- connection = Excon.new('https://127.0.0.1:9443', :ssl_verify_peer => true, :ssl_cert_store => ssl_cert_store )
181
- true
182
- end
183
-
184
- tests('response.status').returns(200) do
185
- response = connection.request(:method => :get, :path => '/content-length/100')
186
-
187
- response.status
188
- end
189
- end
190
- end
191
-
192
- Shindo.tests('Excon basics (ssl file)',['focus']) do
193
- with_rackup('ssl_verify_peer.ru') do
194
-
195
- tests('GET /content-length/100').raises(Excon::Errors::SocketError) do
196
- connection = Excon::Connection.new({
197
- :host => '127.0.0.1',
198
- :hostname => '127.0.0.1',
199
- :nonblock => false,
200
- :port => 8443,
201
- :scheme => 'https',
202
- :ssl_verify_peer => false
203
- })
204
- connection.request(:method => :get, :path => '/content-length/100')
205
- end
206
-
207
- cert_key_path = File.join(File.dirname(__FILE__), 'data', 'excon.cert.key')
208
- cert_crt_path = File.join(File.dirname(__FILE__), 'data', 'excon.cert.crt')
209
- basic_tests('https://127.0.0.1:8443', client_key: cert_key_path, client_cert: cert_crt_path)
210
-
211
- cert_key_data = File.read cert_key_path
212
- cert_crt_data = File.read cert_crt_path
213
- basic_tests('https://127.0.0.1:8443', client_key_data: cert_key_data, client_cert_data: cert_crt_data)
214
- end
215
- end
216
-
217
- Shindo.tests('Excon basics (ssl file paths)',['focus']) do
218
- with_rackup('ssl_verify_peer.ru') do
219
-
220
- tests('GET /content-length/100').raises(Excon::Errors::SocketError) do
221
- connection = Excon::Connection.new({
222
- :host => '127.0.0.1',
223
- :hostname => '127.0.0.1',
224
- :nonblock => false,
225
- :port => 8443,
226
- :scheme => 'https',
227
- :ssl_verify_peer => false
228
- })
229
- connection.request(:method => :get, :path => '/content-length/100')
230
- end
231
-
232
- basic_tests('https://127.0.0.1:8443',
233
- :private_key_path => File.join(File.dirname(__FILE__), 'data', 'excon.cert.key'),
234
- :certificate_path => File.join(File.dirname(__FILE__), 'data', 'excon.cert.crt')
235
- )
236
-
237
- end
238
- end
239
-
240
- Shindo.tests('Excon basics (ssl string)', ['focus']) do
241
- with_rackup('ssl_verify_peer.ru') do
242
- basic_tests('https://127.0.0.1:8443',
243
- :private_key => File.read(File.join(File.dirname(__FILE__), 'data', 'excon.cert.key')),
244
- :certificate => File.read(File.join(File.dirname(__FILE__), 'data', 'excon.cert.crt'))
245
- )
246
- end
247
- end
248
-
249
- Shindo.tests('Excon basics (Unix socket)') do
250
- pending if RUBY_PLATFORM == 'java' # need to find suitable server for jruby
251
-
252
- file_name = '/tmp/unicorn.sock'
253
- with_unicorn('basic.ru', 'unix://'+file_name) do
254
- basic_tests("unix:/", :socket => file_name)
255
-
256
- tests('explicit uri passed to connection') do
257
- tests('GET /content-length/100').returns(200) do
258
- connection = Excon::Connection.new({
259
- :socket => file_name,
260
- :nonblock => false,
261
- :scheme => 'unix',
262
- :ssl_verify_peer => false
263
- })
264
- response = connection.request(:method => :get, :path => '/content-length/100')
265
- response[:status]
266
- end
267
- end
268
-
269
- tests('http Host header is empty') do
270
- tests('GET /headers').returns("") do
271
- connection = Excon::Connection.new({
272
- :socket => file_name,
273
- :nonblock => false,
274
- :scheme => 'unix',
275
- :ssl_verify_peer => false
276
- })
277
- response = connection.request(:method => :get, :path => '/headers')
278
- JSON.parse(response.body)['HTTP_HOST']
279
- end
280
- end
281
- end
282
- end
283
-
284
- Shindo.tests('Excon basics (reusable local port)') do
285
- class CustomSocket < Socket
286
- def initialize
287
- super(AF_INET, SOCK_STREAM, 0)
288
- setsockopt(SOL_SOCKET, SO_REUSEADDR, true)
289
- if defined?(SO_REUSEPORT)
290
- setsockopt(SOL_SOCKET, SO_REUSEPORT, true)
291
- end
292
- end
293
-
294
- def bind(address, port)
295
- super(Socket.pack_sockaddr_in(port, address))
296
- end
297
-
298
- def connect(address, port)
299
- super(Socket.pack_sockaddr_in(port, address))
300
- end
301
-
302
- def http_get(path)
303
- print "GET /content-length/10 HTTP/1.0\r\n\r\n"
304
- read.split("\r\n\r\n", 2)[1]
305
- end
306
-
307
- def self.ip_address_list
308
- if Socket.respond_to?(:ip_address_list)
309
- Socket.ip_address_list.select(&:ipv4?).map(&:ip_address)
310
- else
311
- `ifconfig`.scan(/inet.*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/).flatten
312
- end
313
- end
314
-
315
- def self.find_alternate_ip(ip)
316
- ip_address_list.detect {|a| a != ip } || '127.0.0.1'
317
- end
318
- end
319
-
320
- with_rackup('basic.ru', '0.0.0.0') do
321
- connection = Excon.new("http://127.0.0.1:9292/echo",
322
- :reuseaddr => true, # enable address and port reuse
323
- :persistent => true # keep the socket open
324
- )
325
- response = connection.get
326
-
327
- tests('has a local port').returns(true) do
328
- response.local_port.to_s =~ /\d{4,5}/ ? true : false
329
- end
330
-
331
- tests('local port can be re-bound').returns('x' * 10) do
332
- # create a socket with address/port reuse enabled
333
- s = CustomSocket.new
334
-
335
- # bind to the same local port and address used in the get above (won't work without reuse options on both sockets)
336
- s.bind(response.local_address, response.local_port)
337
-
338
- # connect to the server on a different address than was used for the initial connection to avoid duplicate 5-tuples of: {protcol, src_port, src_addr, dst_port, dst_addr}
339
- s.connect(CustomSocket.find_alternate_ip(response.local_address), 9292)
340
-
341
- # send the request
342
- body = s.http_get("/content-length/10")
343
-
344
- # close both the sockets
345
- s.close
346
- connection.reset
347
-
348
- body
349
- end
350
- end
351
- end