httpi 2.4.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/development.yml +48 -0
  3. data/CHANGELOG.md +45 -0
  4. data/Gemfile +10 -5
  5. data/README.md +20 -16
  6. data/Rakefile +5 -3
  7. data/UPDATING.md +7 -0
  8. data/httpi.gemspec +6 -7
  9. data/lib/httpi/adapter/curb.rb +8 -2
  10. data/lib/httpi/adapter/em_http.rb +5 -4
  11. data/lib/httpi/adapter/excon.rb +17 -5
  12. data/lib/httpi/adapter/http.rb +15 -2
  13. data/lib/httpi/adapter/httpclient.rb +16 -4
  14. data/lib/httpi/adapter/net_http.rb +42 -16
  15. data/lib/httpi/adapter/net_http_persistent.rb +6 -2
  16. data/lib/httpi/adapter/rack.rb +13 -6
  17. data/lib/httpi/auth/ssl.rb +68 -3
  18. data/lib/httpi/logger.rb +6 -1
  19. data/lib/httpi/request.rb +12 -5
  20. data/lib/httpi/response.rb +2 -0
  21. data/lib/httpi/version.rb +1 -1
  22. data/lib/httpi.rb +4 -4
  23. data/spec/fixtures/client_cert.pem +18 -14
  24. data/spec/fixtures/client_key.pem +25 -13
  25. data/spec/httpi/adapter/curb_spec.rb +36 -10
  26. data/spec/httpi/adapter/em_http_spec.rb +23 -21
  27. data/spec/httpi/adapter/excon_spec.rb +28 -90
  28. data/spec/httpi/adapter/http_spec.rb +23 -96
  29. data/spec/httpi/adapter/httpclient_spec.rb +46 -4
  30. data/spec/httpi/adapter/net_http_persistent_spec.rb +31 -81
  31. data/spec/httpi/adapter/net_http_spec.rb +39 -99
  32. data/spec/httpi/adapter/rack_spec.rb +6 -8
  33. data/spec/httpi/auth/ssl_spec.rb +49 -1
  34. data/spec/httpi/httpi_spec.rb +16 -4
  35. data/spec/httpi/request_spec.rb +5 -0
  36. data/spec/integration/curb_spec.rb +20 -0
  37. data/spec/integration/em_http_spec.rb +19 -2
  38. data/spec/integration/excon_spec.rb +174 -0
  39. data/spec/integration/fixtures/ca_all.pem +17 -42
  40. data/spec/integration/fixtures/server.cert +17 -17
  41. data/spec/integration/fixtures/server.key +25 -13
  42. data/spec/integration/http_spec.rb +156 -0
  43. data/spec/integration/httpclient_spec.rb +20 -0
  44. data/spec/integration/net_http_persistent_spec.rb +34 -2
  45. data/spec/integration/net_http_spec.rb +144 -1
  46. data/spec/integration/support/application.rb +4 -2
  47. data/spec/integration/support/server.rb +1 -2
  48. data/spec/spec_helper.rb +0 -2
  49. metadata +31 -29
  50. data/.travis.yml +0 -8
@@ -10,11 +10,22 @@ module HTTPI
10
10
 
11
11
  VERIFY_MODES = [:none, :peer, :fail_if_no_peer_cert, :client_once]
12
12
  CERT_TYPES = [:pem, :der]
13
- SSL_VERSIONS = OpenSSL::SSL::SSLContext::METHODS.reject { |method| method.match /server|client/ }.sort.reverse
13
+
14
+ # Fix for
15
+ # httpi/auth/ssl.rb:13: warning: constant OpenSSL::SSL::SSLContext::METHODS is deprecated
16
+ ssl_context = OpenSSL::SSL::SSLContext
17
+ SSL_VERSIONS = if ssl_context.const_defined? :METHODS_MAP
18
+ ssl_context.const_get(:METHODS_MAP).keys
19
+ else
20
+ ssl_context::METHODS.reject { |method| method.match(/server|client/) }
21
+ end.sort.reverse
22
+
23
+ # Returns OpenSSL::SSL::*_VERSION values for min_version and max_version
24
+ MIN_MAX_VERSIONS = OpenSSL::SSL.constants.select{|constant| constant =~/_VERSION$/}.map{|version| version.to_s.gsub(/_VERSION$/,'').to_sym}.reverse
14
25
 
15
26
  # Returns whether SSL configuration is present.
16
27
  def present?
17
- (verify_mode == :none) || (cert && cert_key) || ca_cert_file
28
+ (verify_mode == :none) || (cert && cert_key) || ca_cert_file || ciphers
18
29
  rescue TypeError, Errno::ENOENT
19
30
  false
20
31
  end
@@ -31,6 +42,30 @@ module HTTPI
31
42
  # Accessor for the cacert file to validate SSL certificates.
32
43
  attr_accessor :ca_cert_file
33
44
 
45
+ # Accessor for the ca_path to validate SSL certificates.
46
+ attr_accessor :ca_cert_path
47
+
48
+ # Certificate store holds trusted CA certificates used to verify peer certificates.
49
+ attr_accessor :cert_store
50
+
51
+ # Accessor for the SSL ciphers list.
52
+ attr_reader :ciphers
53
+
54
+ # Sets the available symmetric algorithms for encryption and decryption.
55
+ # @see OpenSSL::SSL::SSLContext#ciphers
56
+ # @example
57
+ # ssl.ciphers = "cipher1:cipher2:..."
58
+ # ssl.ciphers = [name, ...]
59
+ # ssl.ciphers = [[name, version, bits, alg_bits], ...]
60
+ def ciphers=(ciphers)
61
+ @ciphers =
62
+ if ciphers
63
+ context = OpenSSL::SSL::SSLContext.new
64
+ context.ciphers = ciphers
65
+ context.ciphers.map(&:first)
66
+ end
67
+ end
68
+
34
69
  # Returns the cert type to validate SSL certificates PEM|DER.
35
70
  def cert_type
36
71
  @cert_type ||= :pem
@@ -63,7 +98,7 @@ module HTTPI
63
98
 
64
99
  # Returns the SSL version number. Defaults to <tt>nil</tt> (auto-negotiate).
65
100
  def ssl_version
66
- @ssl_version
101
+ @ssl_version ||= nil
67
102
  end
68
103
 
69
104
  # Sets the SSL version number. Expects one of <tt>HTTPI::Auth::SSL::SSL_VERSIONS</tt>.
@@ -76,6 +111,36 @@ module HTTPI
76
111
  @ssl_version = version
77
112
  end
78
113
 
114
+ # Returns the SSL min_version number. Defaults to <tt>nil</tt> (auto-negotiate).
115
+ def min_version
116
+ @min_version ||= nil
117
+ end
118
+
119
+ # Sets the SSL min_version number. Expects one of <tt>HTTPI::Auth::SSL::MIN_MAX_VERSIONS</tt>.
120
+ def min_version=(version)
121
+ unless MIN_MAX_VERSIONS.include? version
122
+ raise ArgumentError, "Invalid SSL min_version #{version.inspect}\n" +
123
+ "Please specify one of #{MIN_MAX_VERSIONS.inspect}"
124
+ end
125
+
126
+ @min_version = version
127
+ end
128
+
129
+ # Returns the SSL min_version number. Defaults to <tt>nil</tt> (auto-negotiate).
130
+ def max_version
131
+ @max_version ||= nil
132
+ end
133
+
134
+ # Sets the SSL min_version number. Expects one of <tt>HTTPI::Auth::SSL::MIN_MAX_VERSIONS</tt>.
135
+ def max_version=(version)
136
+ unless MIN_MAX_VERSIONS.include? version
137
+ raise ArgumentError, "Invalid SSL max_version #{version.inspect}\n" +
138
+ "Please specify one of #{MIN_MAX_VERSIONS.inspect}"
139
+ end
140
+
141
+ @max_version = version
142
+ end
143
+
79
144
  # Returns an <tt>OpenSSL::X509::Certificate</tt> for the +cert_file+.
80
145
  def cert
81
146
  @cert ||= (OpenSSL::X509::Certificate.new File.read(cert_file) if cert_file)
data/lib/httpi/logger.rb CHANGED
@@ -43,8 +43,13 @@ module HTTPI
43
43
  protected
44
44
 
45
45
  def log_request(method, request, adapter)
46
- log("HTTPI #{method.to_s.upcase} request to #{request.url.host} (#{adapter})")
46
+ log("HTTPI #{request_ssl_info(request)} #{method.to_s.upcase} request to #{request.url.host} (#{adapter})")
47
47
  end
48
48
 
49
+ def request_ssl_info(request)
50
+ if request.auth && request.auth.ssl
51
+ "#{request.auth.ssl.ssl_version}/#{request.auth.ssl.verify_mode}"
52
+ end
53
+ end
49
54
  end
50
55
  end
data/lib/httpi/request.rb CHANGED
@@ -11,7 +11,7 @@ module HTTPI
11
11
  class Request
12
12
 
13
13
  # Available attribute writers.
14
- ATTRIBUTES = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout, :follow_redirect, :query]
14
+ ATTRIBUTES = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout, :write_timeout, :follow_redirect, :redirect_limit, :query]
15
15
 
16
16
  # Accepts a Hash of +args+ to mass assign attributes and authentication credentials.
17
17
  def initialize(args = {})
@@ -56,8 +56,7 @@ module HTTPI
56
56
 
57
57
  # Returns whether to use SSL.
58
58
  def ssl?
59
- return @ssl unless @ssl.nil?
60
- !!(url.to_s =~ /^https/)
59
+ @ssl ||= !!(url.to_s =~ /^https/)
61
60
  end
62
61
 
63
62
  # Sets whether to use SSL.
@@ -91,7 +90,7 @@ module HTTPI
91
90
  headers["Cookie"] = cookies if cookies
92
91
  end
93
92
 
94
- attr_accessor :open_timeout, :read_timeout
93
+ attr_accessor :open_timeout, :read_timeout, :write_timeout
95
94
  attr_reader :body
96
95
 
97
96
  # Sets a body request given a String or a Hash.
@@ -102,6 +101,7 @@ module HTTPI
102
101
  # Sets the block to be called while processing the response. The block
103
102
  # accepts a single parameter - the chunked response body.
104
103
  def on_body(&block)
104
+ @on_body ||= nil
105
105
  if block_given? then
106
106
  @on_body = block
107
107
  end
@@ -130,6 +130,13 @@ module HTTPI
130
130
  @follow_redirect ||= false
131
131
  end
132
132
 
133
+ attr_writer :redirect_limit
134
+
135
+ # Returns how many redirects should be followed - defaults to 3 if not set.
136
+ def redirect_limit
137
+ @redirect_limit ||= 3
138
+ end
139
+
133
140
  private
134
141
 
135
142
  # Stores the cookies from past requests.
@@ -139,7 +146,7 @@ module HTTPI
139
146
 
140
147
  # Expects a +url+, validates its validity and returns a +URI+ object.
141
148
  def normalize_url!(url)
142
- raise ArgumentError, "Invalid URL: #{url}" unless url.to_s =~ /^http/
149
+ raise ArgumentError, "Invalid URL: #{url}" unless url.to_s =~ /^http|socks/
143
150
  url.kind_of?(URI) ? url : URI(url)
144
151
  end
145
152
 
@@ -44,12 +44,14 @@ module HTTPI
44
44
 
45
45
  # Returns any DIME attachments.
46
46
  def attachments
47
+ @body ||= nil
47
48
  decode_body unless @body
48
49
  @attachments ||= []
49
50
  end
50
51
 
51
52
  # Returns the HTTP response body.
52
53
  def body
54
+ @body ||= nil
53
55
  decode_body unless @body
54
56
  @body
55
57
  end
data/lib/httpi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTPI
2
- VERSION = '2.4.1'
2
+ VERSION = '3.0.0'
3
3
  end
data/lib/httpi.rb CHANGED
@@ -103,7 +103,7 @@ module HTTPI
103
103
  class << self
104
104
 
105
105
  def query_builder
106
- @query_builder || HTTPI::QueryBuilder::Flat
106
+ @query_builder ||= HTTPI::QueryBuilder::Flat
107
107
  end
108
108
 
109
109
  def query_builder=(builder)
@@ -152,7 +152,7 @@ module HTTPI
152
152
  end
153
153
 
154
154
  # Executes an HTTP request for the given +method+.
155
- def request(method, request, adapter = nil)
155
+ def request(method, request, adapter = nil, redirects = 0)
156
156
  adapter_class = load_adapter(adapter, request)
157
157
 
158
158
  yield adapter_class.client if block_given?
@@ -160,10 +160,10 @@ module HTTPI
160
160
 
161
161
  response = adapter_class.request(method)
162
162
 
163
- if response && HTTPI::Response::RedirectResponseCodes.member?(response.code) && request.follow_redirect?
163
+ if response && HTTPI::Response::RedirectResponseCodes.member?(response.code) && request.follow_redirect? && redirects < request.redirect_limit
164
164
  request.url = URI.join(request.url, response.headers['location'])
165
165
  log("Following redirect: '#{request.url}'.")
166
- return request(method, request, adapter)
166
+ return request(method, request, adapter, redirects + 1)
167
167
  end
168
168
 
169
169
  response
@@ -1,16 +1,20 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIICbTCCAdYCCQDC4v8d04615DANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJE
3
- RTEQMA4GA1UECBMHSGFtYnVyZzEQMA4GA1UEBxMHSGFtYnVyZzEOMAwGA1UEChMF
4
- aHR0cGkxFDASBgNVBAMTC2V4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFt
5
- cGxlQGV4YW1wbGUuY29tMB4XDTEwMTAxNTE4NTg0N1oXDTExMTAxNTE4NTg0N1ow
6
- ezELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1
7
- cmcxDjAMBgNVBAoTBWh0dHBpMRQwEgYDVQQDEwtleGFtcGxlLmNvbTEiMCAGCSqG
8
- SIb3DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOB
9
- jQAwgYkCgYEAvJiaojIFQAbFczXkBmjxpxra9LbQm0VIESFSl8uBSjmG/gmCBwKg
10
- 8O94P3tAjDNClC+fEqBLE37KH4qe76yw7upgRruP5jQzUEL1yCaVtA/DoqgaCxZy
11
- 7VhB2A3f71Zw6kQPt3BOME68fnGsTX65x9XAawCGzGmJSk/Z6wvml1MCAwEAATAN
12
- BgkqhkiG9w0BAQUFAAOBgQCxOyni9LOKf17vUKVG8Y4TBzRYwm8/hlEdVEU3JKG0
13
- /aCCwIJLHl+z+3L4r81IN3+YKrHilqx9K0emboJbBRQklYsv/AE+J44Bq3llRiro
14
- 0e5zwH61jb1j+kxhcxoGiiy8R7hYho24ljuMgFGqtK3kZSP/t9tBLLVp+ItWQ6xX
15
- 5g==
2
+ MIIDVTCCAj2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQKDBhEZXZl
3
+ bG9wbWVudC9DTj1sb2NhbGhvc3QwHhcNMTgwODEwMDAzMTQzWhcNMjgwODA3MDAz
4
+ MTQzWjAjMSEwHwYDVQQKDBhEZXZlbG9wbWVudC9DTj1sb2NhbGhvc3QwggEiMA0G
5
+ CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbU3vifU9omTx5T6ECuYnvryr4iWPP
6
+ A4sXhduO8aD3IdA8zHlPtZnmh0liE30nAY00xKa4Eisxs9/UgUoHlEb5nCtYs6Od
7
+ 9pjiuyry2G5lBHIhLlVNTbReRKfjhr3ewUxcnQN0xiynjfsUMbzoVI1ZsGDWZ9gF
8
+ 4DHg3Accee3+/BNBDTWixYXh64D9YI1Tj/3fC1I2taUp32jdLXE9mbCByQlk5EZf
9
+ BZUWx868FtwwzU3ymbq2uQQtTl5a0QHqLUwb0nkdewoRvaZJFkopI+1tgy0Hs+pY
10
+ QM99vQWS7ViM5qbVYtPil/4VVWJbx/kQi/To4/Q8TxYbIRkoeJSOq9U3AgMBAAGj
11
+ gZMwgZAwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU4W1eb4Zc4NOpBe8UXcmIzLHB
12
+ FFQwSwYDVR0jBEQwQoAU4W1eb4Zc4NOpBe8UXcmIzLHBFFShJ6QlMCMxITAfBgNV
13
+ BAoMGERldmVsb3BtZW50L0NOPWxvY2FsaG9zdIIBATAUBgNVHREEDTALgglsb2Nh
14
+ bGhvc3QwDQYJKoZIhvcNAQELBQADggEBAM7oYR6eVIascNLhgfJFboVernRl137Y
15
+ 7hyjBQTSleMame/VN1MwMscUYpen8rFu9lUviKe9fxV/7OqNR4vvZ83ttbb+CxJ7
16
+ 3mwoQHufjrGcxsWUKrmtJsXAGZpGJFw7ygnKDAfDPKWSKYeUuQ417AutPWSvhWqa
17
+ LEohhNCeHJj/+3U2vj2g2rvy0AASeMff9IMz/lpPZ2bjJQjlITXXPvswB2/uZSRT
18
+ KWEifqfo03/nTjhzN7dz2hXEeZHroCq6FZa1R6smYVM79TORFWiKfdKtjXI8wQQ2
19
+ BhVJpWQB2yw9d/4Q7x2EPjJEPiVoRLW0vF8uxr++14nhVkSpYJCSNAw=
16
20
  -----END CERTIFICATE-----
@@ -1,15 +1,27 @@
1
1
  -----BEGIN RSA PRIVATE KEY-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
15
27
  -----END RSA PRIVATE KEY-----
@@ -20,7 +20,7 @@ unless RUBY_PLATFORM =~ /java/
20
20
  it "supports ntlm authentication" do
21
21
  request = HTTPI::Request.new(@server.url + "ntlm-auth")
22
22
  adapter = HTTPI::Adapter::Curb.new(request)
23
-
23
+
24
24
  request.auth.ntlm("tester", "vReqSoafRe5O")
25
25
  expect(adapter.request(:get).body).to eq("ntlm-auth")
26
26
  end
@@ -146,29 +146,36 @@ unless RUBY_PLATFORM =~ /java/
146
146
  end
147
147
  end
148
148
 
149
- describe "timeout" do
149
+ describe "timeout_ms" do
150
150
  it "is not set unless it's specified" do
151
- curb.expects(:timeout=).never
151
+ curb.expects(:timeout_ms=).never
152
152
  adapter.request(:get)
153
153
  end
154
154
 
155
- it "is set if specified" do
155
+ it "is set if specified read_timeout" do
156
156
  request.read_timeout = 30
157
- curb.expects(:timeout=).with(request.read_timeout)
157
+ curb.expects(:timeout_ms=).with(30_000)
158
+
159
+ adapter.request(:get)
160
+ end
161
+
162
+ it "is set if specified write_timeout" do
163
+ request.write_timeout = 30
164
+ curb.expects(:timeout_ms=).with(30_000)
158
165
 
159
166
  adapter.request(:get)
160
167
  end
161
168
  end
162
169
 
163
- describe "connect_timeout" do
170
+ describe "connect_timeout_ms" do
164
171
  it "is not set unless it's specified" do
165
- curb.expects(:connect_timeout=).never
172
+ curb.expects(:connect_timeout_ms=).never
166
173
  adapter.request(:get)
167
174
  end
168
175
 
169
176
  it "is set if specified" do
170
177
  request.open_timeout = 30
171
- curb.expects(:connect_timeout=).with(30)
178
+ curb.expects(:connect_timeout_ms=).with(30_000)
172
179
 
173
180
  adapter.request(:get)
174
181
  end
@@ -243,6 +250,13 @@ unless RUBY_PLATFORM =~ /java/
243
250
  request
244
251
  end
245
252
 
253
+ it 'sets ssl_cipher_list' do
254
+ request.auth.ssl.ciphers = ["AES128"]
255
+ curb.expects(:set).with(any_parameters).at_least(1)
256
+ curb.expects(:set).with(:ssl_cipher_list, anything)
257
+ adapter.request(:get)
258
+ end
259
+
246
260
  context 'sets ssl_version' do
247
261
  it 'defaults to nil when no ssl_version is specified' do
248
262
  curb.expects(:ssl_version=).with(nil)
@@ -257,8 +271,7 @@ unless RUBY_PLATFORM =~ /java/
257
271
  end
258
272
 
259
273
  it 'to 2 when ssl_version is specified as SSLv2/SSLv23' do
260
- version = OpenSSL::SSL::SSLContext::METHODS.reject { |method| method.match /server|client/ }
261
- version = version.select { |method| method.to_s.match /SSLv2|SSLv23/ }.first
274
+ version = HTTPI::Auth::SSL::SSL_VERSIONS.select { |method| method.to_s.match(/SSLv2|SSLv23/) }.first
262
275
  request.auth.ssl.ssl_version = version
263
276
  curb.expects(:ssl_version=).with(2)
264
277
 
@@ -272,6 +285,16 @@ unless RUBY_PLATFORM =~ /java/
272
285
  adapter.request(:get)
273
286
  end
274
287
  end
288
+ it 'raises error when min_version not nil' do
289
+ request.auth.ssl.min_version = :TLS1_2
290
+ expect{ adapter.request(:get) }.
291
+ to raise_error(HTTPI::NotSupportedError, 'Curb adapter does not support #min_version or #max_version. Please, use #ssl_version instead.')
292
+ end
293
+ it 'raises error when max_version not nil' do
294
+ request.auth.ssl.max_version = :TLS1_2
295
+ expect{ adapter.request(:get) }.
296
+ to raise_error(HTTPI::NotSupportedError, 'Curb adapter does not support #min_version or #max_version. Please, use #ssl_version instead.')
297
+ end
275
298
  end
276
299
 
277
300
  context "(for SSL client auth)" do
@@ -279,6 +302,7 @@ unless RUBY_PLATFORM =~ /java/
279
302
  request = HTTPI::Request.new("http://example.com")
280
303
  request.auth.ssl.cert_key_file = "spec/fixtures/client_key.pem"
281
304
  request.auth.ssl.cert_file = "spec/fixtures/client_cert.pem"
305
+ request.auth.ssl.cert_key_password = 'example'
282
306
  request
283
307
  end
284
308
 
@@ -287,6 +311,7 @@ unless RUBY_PLATFORM =~ /java/
287
311
  curb.expects(:ssl_verify_host=).with(0) # avoid "SSL peer certificate" error
288
312
  curb.expects(:cert_key=).with(request.auth.ssl.cert_key_file)
289
313
  curb.expects(:cert=).with(request.auth.ssl.cert_file)
314
+ curb.expects(:certpassword=).with(request.auth.ssl.cert_key_password)
290
315
 
291
316
  adapter.request(:get)
292
317
  end
@@ -294,6 +319,7 @@ unless RUBY_PLATFORM =~ /java/
294
319
  it "cert_key, cert and ssl_verify_peer should be set" do
295
320
  curb.expects(:cert_key=).with(request.auth.ssl.cert_key_file)
296
321
  curb.expects(:cert=).with(request.auth.ssl.cert_file)
322
+ curb.expects(:certpassword=).with(request.auth.ssl.cert_key_password)
297
323
  curb.expects(:ssl_verify_peer=).with(true)
298
324
  curb.expects(:certtype=).with(request.auth.ssl.cert_type.to_s.upcase)
299
325
 
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
  require "httpi/adapter/em_http"
3
3
  require "httpi/request"
4
4
 
5
- begin
5
+ unless RUBY_PLATFORM =~ /java/
6
6
  HTTPI::Adapter.load_adapter(:em_http)
7
7
 
8
8
  describe HTTPI::Adapter::EmHttpRequest do
@@ -89,15 +89,12 @@ begin
89
89
  end
90
90
 
91
91
  it "sets host, port and authorization" do
92
- url = 'http://example.com:80'
93
-
92
+ url = "http://example.com:80"
94
93
  connection_options = {
95
- :connect_timeout => nil,
96
- :inactivity_timeout => nil,
97
- :proxy => {
98
- :host => 'proxy-host.com',
99
- :port => 443,
100
- :authorization => ['username', 'password']
94
+ :proxy => {
95
+ :host => "proxy-host.com",
96
+ :port => 443,
97
+ :authorization => ["username", "password"]
101
98
  }
102
99
  }
103
100
 
@@ -111,8 +108,8 @@ begin
111
108
  it "is passed as a connection option" do
112
109
  request.open_timeout = 30
113
110
 
114
- url = 'http://example.com:80'
115
- connection_options = { :connect_timeout => 30, :inactivity_timeout => nil }
111
+ url = "http://example.com:80"
112
+ connection_options = { connect_timeout: 30 }
116
113
 
117
114
  EventMachine::HttpRequest.expects(:new).with(url, connection_options)
118
115
 
@@ -121,11 +118,22 @@ begin
121
118
  end
122
119
 
123
120
  describe "receive_timeout" do
124
- it "is passed as a connection option" do
121
+ it "is passed as a connection option (when read_timeout specified)" do
125
122
  request.read_timeout = 60
126
123
 
127
- url = 'http://example.com:80'
128
- connection_options = { :connect_timeout => nil, :inactivity_timeout => 60 }
124
+ url = "http://example.com:80"
125
+ connection_options = { inactivity_timeout: 60 }
126
+
127
+ EventMachine::HttpRequest.expects(:new).with(url, connection_options)
128
+
129
+ adapter
130
+ end
131
+
132
+ it "is passed as a connection option (when write_timeout specified)" do
133
+ request.write_timeout = 60
134
+
135
+ url = "http://example.com:80"
136
+ connection_options = { inactivity_timeout: 60 }
129
137
 
130
138
  EventMachine::HttpRequest.expects(:new).with(url, connection_options)
131
139
 
@@ -142,7 +150,7 @@ begin
142
150
 
143
151
  it "raises an error for HTTP digest auth" do
144
152
  request.auth.digest "username", "password"
145
- expect { adapter.request(:get) }.to raise_error
153
+ expect { adapter.request(:get) }.to raise_error HTTPI::NotSupportedError
146
154
  end
147
155
  end
148
156
 
@@ -169,10 +177,4 @@ begin
169
177
  end
170
178
 
171
179
  end
172
- rescue LoadError => e
173
- if e.message =~ /fiber/
174
- warn "LoadError: #{e.message} (EventMachine requires fibers)"
175
- else
176
- raise e
177
- end
178
180
  end
@@ -1,96 +1,34 @@
1
1
  require "spec_helper"
2
- require "integration/support/server"
3
-
4
- describe HTTPI::Adapter::Excon do
5
-
6
- subject(:adapter) { :excon }
7
-
8
- context "http requests" do
9
- before :all do
10
- @server = IntegrationServer.run
11
- end
12
-
13
- after :all do
14
- @server.stop
15
- end
16
-
17
- it "sends and receives HTTP headers" do
18
- request = HTTPI::Request.new(@server.url + "x-header")
19
- request.headers["X-Header"] = "HTTPI"
20
-
21
- response = HTTPI.get(request, adapter)
22
- expect(response.body).to include("HTTPI")
23
- end
24
-
25
- it "executes GET requests" do
26
- response = HTTPI.get(@server.url, adapter)
27
- expect(response.body).to eq("get")
28
- expect(response.headers["Content-Type"]).to eq("text/plain")
29
- end
30
-
31
- it "executes POST requests" do
32
- response = HTTPI.post(@server.url, "<some>xml</some>", adapter)
33
- expect(response.body).to eq("post")
34
- expect(response.headers["Content-Type"]).to eq("text/plain")
35
- end
36
-
37
- it "executes HEAD requests" do
38
- response = HTTPI.head(@server.url, adapter)
39
- expect(response.code).to eq(200)
40
- expect(response.headers["Content-Type"]).to eq("text/plain")
41
- end
42
-
43
- it "executes PUT requests" do
44
- response = HTTPI.put(@server.url, "<some>xml</some>", adapter)
45
- expect(response.body).to eq("put")
46
- expect(response.headers["Content-Type"]).to eq("text/plain")
47
- end
48
-
49
- it "executes DELETE requests" do
50
- response = HTTPI.delete(@server.url, adapter)
51
- expect(response.body).to eq("delete")
52
- expect(response.headers["Content-Type"]).to eq("text/plain")
53
- end
54
-
55
- it "supports basic authentication" do
56
- request = HTTPI::Request.new(@server.url + "basic-auth")
57
- request.auth.basic("admin", "secret")
58
-
59
- response = HTTPI.get(request, adapter)
60
- expect(response.body).to eq("basic-auth")
61
- end
62
-
63
- it "does not support ntlm authentication" do
64
- request = HTTPI::Request.new(@server.url + "ntlm-auth")
65
- request.auth.ntlm("tester", "vReqSoafRe5O")
66
-
67
- expect { HTTPI.get(request, adapter) }.
68
- to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/)
69
- end
70
- end
71
-
72
- # it does not support digest auth
73
-
74
- if RUBY_PLATFORM =~ /java/
75
- pending "Puma Server complains: SSL not supported on JRuby"
76
- else
77
- context "https requests" do
78
- before :all do
79
- @server = IntegrationServer.run(:ssl => true)
2
+ require "httpi/adapter/excon"
3
+ require "httpi/request"
4
+
5
+ begin
6
+ HTTPI::Adapter.load_adapter(:excon)
7
+
8
+ describe HTTPI::Adapter::Excon do
9
+ let(:adapter) { HTTPI::Adapter::Excon.new(request) }
10
+ let(:request) { HTTPI::Request.new("http://example.com") }
11
+
12
+ describe "settings" do
13
+ describe "connect_timeout, read_timeout, write_timeout" do
14
+ it "are passed as connection options" do
15
+ request.open_timeout = 30
16
+ request.read_timeout = 40
17
+ request.write_timeout = 50
18
+
19
+ expect(adapter.client.data).to include(
20
+ connect_timeout: 30,
21
+ read_timeout: 40,
22
+ write_timeout: 50
23
+ )
24
+ end
80
25
  end
81
- after :all do
82
- @server.stop
83
- end
84
-
85
- # it does not raise when no certificate was set up
86
- it "works when set up properly" do
87
- request = HTTPI::Request.new(@server.url)
88
- request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
89
-
90
- response = HTTPI.get(request, adapter)
91
- expect(response.body).to eq("get")
26
+ describe "host, hostname" do
27
+ it "both are set" do
28
+ Excon.expects(:display_warning).never
29
+ expect(adapter.client.data).to include(host: 'example.com', hostname: 'example.com')
30
+ end
92
31
  end
93
32
  end
94
33
  end
95
-
96
34
  end