httpi-ntlm 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.autotest +5 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +69 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE +20 -0
  8. data/README.md +223 -0
  9. data/Rakefile +18 -0
  10. data/autotest/discover.rb +1 -0
  11. data/httpi-ntlm.gemspec +27 -0
  12. data/lib/httpi-ntlm.rb +1 -0
  13. data/lib/httpi.rb +198 -0
  14. data/lib/httpi/adapter.rb +67 -0
  15. data/lib/httpi/adapter/curb.rb +125 -0
  16. data/lib/httpi/adapter/httpclient.rb +98 -0
  17. data/lib/httpi/adapter/net_http.rb +117 -0
  18. data/lib/httpi/auth/config.rb +81 -0
  19. data/lib/httpi/auth/ssl.rb +91 -0
  20. data/lib/httpi/dime.rb +56 -0
  21. data/lib/httpi/request.rb +90 -0
  22. data/lib/httpi/response.rb +85 -0
  23. data/lib/httpi/version.rb +5 -0
  24. data/spec/fixtures/attachment.gif +0 -0
  25. data/spec/fixtures/client_cert.pem +16 -0
  26. data/spec/fixtures/client_key.pem +15 -0
  27. data/spec/fixtures/xml.gz +0 -0
  28. data/spec/fixtures/xml.xml +10 -0
  29. data/spec/fixtures/xml_dime.dime +0 -0
  30. data/spec/fixtures/xml_dime.xml +1 -0
  31. data/spec/httpi/adapter/curb_spec.rb +232 -0
  32. data/spec/httpi/adapter/httpclient_spec.rb +164 -0
  33. data/spec/httpi/adapter/net_http_spec.rb +142 -0
  34. data/spec/httpi/adapter_spec.rb +55 -0
  35. data/spec/httpi/auth/config_spec.rb +117 -0
  36. data/spec/httpi/auth/ssl_spec.rb +128 -0
  37. data/spec/httpi/httpi_spec.rb +284 -0
  38. data/spec/httpi/request_spec.rb +135 -0
  39. data/spec/httpi/response_spec.rb +125 -0
  40. data/spec/integration/request_spec.rb +95 -0
  41. data/spec/integration/server.rb +39 -0
  42. data/spec/spec_helper.rb +12 -0
  43. data/spec/support/fixture.rb +27 -0
  44. data/spec/support/matchers.rb +19 -0
  45. metadata +200 -0
@@ -0,0 +1,128 @@
1
+ require "spec_helper"
2
+ require "httpi/auth/ssl"
3
+
4
+ describe HTTPI::Auth::SSL do
5
+
6
+ describe "VERIFY_MODES" do
7
+ it "contains the supported SSL verify modes" do
8
+ HTTPI::Auth::SSL::VERIFY_MODES.should == [:none, :peer, :fail_if_no_peer_cert, :client_once]
9
+ end
10
+ end
11
+
12
+ describe "#present?" do
13
+ it "defaults to return false" do
14
+ ssl = HTTPI::Auth::SSL.new
15
+ ssl.should_not be_present
16
+ end
17
+
18
+ it "returns false if only a client key was specified" do
19
+ ssl = HTTPI::Auth::SSL.new
20
+ ssl.cert_key_file = "spec/fixtures/client_key.pem"
21
+
22
+ ssl.should_not be_present
23
+ end
24
+
25
+ it "returns false if only a client key was specified" do
26
+ ssl = HTTPI::Auth::SSL.new
27
+ ssl.cert_file = "spec/fixtures/client_cert.pem"
28
+
29
+ ssl.should_not be_present
30
+ end
31
+
32
+ it "returns true if both client key and cert are present" do
33
+ ssl.should be_present
34
+ end
35
+
36
+ it "returns true of the verify_mode is :none" do
37
+ ssl = HTTPI::Auth::SSL.new
38
+ ssl.verify_mode = :none
39
+ ssl.should be_present
40
+ end
41
+ end
42
+
43
+ describe "#verify_mode" do
44
+ it "defaults to return :peer" do
45
+ ssl.verify_mode.should == :peer
46
+ end
47
+
48
+ it "sets the verify mode to use" do
49
+ ssl = HTTPI::Auth::SSL.new
50
+
51
+ ssl.verify_mode = :none
52
+ ssl.verify_mode.should == :none
53
+ end
54
+
55
+ it "raises an ArgumentError if the given mode is not supported" do
56
+ expect { ssl.verify_mode = :invalid }.to raise_error(ArgumentError)
57
+ end
58
+ end
59
+
60
+ describe "#cert" do
61
+ it "returns an OpenSSL::X509::Certificate for the given cert_file" do
62
+ ssl.cert.should be_a(OpenSSL::X509::Certificate)
63
+ end
64
+
65
+ it "returns nil if no cert_file was given" do
66
+ ssl = HTTPI::Auth::SSL.new
67
+ ssl.cert.should be_nil
68
+ end
69
+ end
70
+
71
+ describe "#cert_key" do
72
+ it "returns a OpenSSL::PKey::RSA for the given cert_key" do
73
+ ssl.cert_key.should be_a(OpenSSL::PKey::RSA)
74
+ end
75
+
76
+ it "returns nil if no cert_key_file was given" do
77
+ ssl = HTTPI::Auth::SSL.new
78
+ ssl.cert_key.should be_nil
79
+ end
80
+ end
81
+
82
+ describe "#ca_cert" do
83
+ it "returns an OpenSSL::X509::Certificate for the given ca_cert_file" do
84
+ ssl = HTTPI::Auth::SSL.new
85
+
86
+ ssl.ca_cert_file = "spec/fixtures/client_cert.pem"
87
+ ssl.ca_cert.should be_a(OpenSSL::X509::Certificate)
88
+ end
89
+ end
90
+
91
+ describe "#openssl_verify_mode" do
92
+ it "returns the OpenSSL verify mode for :none" do
93
+ ssl = HTTPI::Auth::SSL.new
94
+
95
+ ssl.verify_mode = :none
96
+ ssl.openssl_verify_mode.should == OpenSSL::SSL::VERIFY_NONE
97
+ end
98
+
99
+ it "returns the OpenSSL verify mode for :peer" do
100
+ ssl = HTTPI::Auth::SSL.new
101
+
102
+ ssl.verify_mode = :peer
103
+ ssl.openssl_verify_mode.should == OpenSSL::SSL::VERIFY_PEER
104
+ end
105
+
106
+ it "returns the OpenSSL verify mode for :fail_if_no_peer_cert" do
107
+ ssl = HTTPI::Auth::SSL.new
108
+
109
+ ssl.verify_mode = :fail_if_no_peer_cert
110
+ ssl.openssl_verify_mode.should == OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
111
+ end
112
+
113
+ it "returns the OpenSSL verify mode for :client_once" do
114
+ ssl = HTTPI::Auth::SSL.new
115
+
116
+ ssl.verify_mode = :client_once
117
+ ssl.openssl_verify_mode.should == OpenSSL::SSL::VERIFY_CLIENT_ONCE
118
+ end
119
+ end
120
+
121
+ def ssl
122
+ ssl = HTTPI::Auth::SSL.new
123
+ ssl.cert_key_file = "spec/fixtures/client_key.pem"
124
+ ssl.cert_file = "spec/fixtures/client_cert.pem"
125
+ ssl
126
+ end
127
+
128
+ end
@@ -0,0 +1,284 @@
1
+ require "spec_helper"
2
+ require "httpi"
3
+
4
+ describe HTTPI do
5
+ let(:client) { HTTPI }
6
+ let(:httpclient) { HTTPI::Adapter.load(:httpclient)[1] }
7
+ let(:curb) { HTTPI::Adapter.load(:curb)[1] }
8
+
9
+ describe ".get(request)" do
10
+ it "executes a GET request using the default adapter" do
11
+ request = HTTPI::Request.new
12
+ httpclient.any_instance.expects(:get).with(request)
13
+
14
+ client.get request
15
+ end
16
+ end
17
+
18
+ describe ".get(request, adapter)" do
19
+ it "executes a GET request using the given adapter" do
20
+ request = HTTPI::Request.new
21
+ curb.any_instance.expects(:get).with(request)
22
+
23
+ client.get request, :curb
24
+ end
25
+ end
26
+
27
+ describe ".get(url)" do
28
+ it "executes a GET request using the default adapter" do
29
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
30
+ httpclient.any_instance.expects(:get).with(instance_of(HTTPI::Request))
31
+
32
+ client.get "http://example.com"
33
+ end
34
+ end
35
+
36
+ describe ".get(url, adapter)" do
37
+ it "executes a GET request using the given adapter" do
38
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
39
+ curb.any_instance.expects(:get).with(instance_of(HTTPI::Request))
40
+
41
+ client.get "http://example.com", :curb
42
+ end
43
+ end
44
+
45
+ describe ".post(request)" do
46
+ it "executes a POST request using the default adapter" do
47
+ request = HTTPI::Request.new
48
+ httpclient.any_instance.expects(:post).with(request)
49
+
50
+ client.post request
51
+ end
52
+ end
53
+
54
+ describe ".post(request, adapter)" do
55
+ it "executes a POST request using the given adapter" do
56
+ request = HTTPI::Request.new
57
+ curb.any_instance.expects(:post).with(request)
58
+
59
+ client.post request, :curb
60
+ end
61
+ end
62
+
63
+ describe ".post(url, body)" do
64
+ it "executes a POST request using the default adapter" do
65
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
66
+ HTTPI::Request.any_instance.expects(:body=).with("<some>xml</some>")
67
+ httpclient.any_instance.expects(:post).with(instance_of(HTTPI::Request))
68
+
69
+ client.post "http://example.com", "<some>xml</some>"
70
+ end
71
+ end
72
+
73
+ describe ".post(url, body, adapter)" do
74
+ it "executes a POST request using the given adapter" do
75
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
76
+ HTTPI::Request.any_instance.expects(:body=).with("<some>xml</some>")
77
+ curb.any_instance.expects(:post).with(instance_of(HTTPI::Request))
78
+
79
+ client.post "http://example.com", "<some>xml</some>", :curb
80
+ end
81
+ end
82
+
83
+ describe ".head(request)" do
84
+ it "executes a HEAD request using the default adapter" do
85
+ request = HTTPI::Request.new
86
+ httpclient.any_instance.expects(:head).with(request)
87
+
88
+ client.head request
89
+ end
90
+ end
91
+
92
+ describe ".head(request, adapter)" do
93
+ it "executes a HEAD request using the given adapter" do
94
+ request = HTTPI::Request.new
95
+ curb.any_instance.expects(:head).with(request)
96
+
97
+ client.head request, :curb
98
+ end
99
+ end
100
+
101
+ describe ".head(url)" do
102
+ it "executes a HEAD request using the default adapter" do
103
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
104
+ httpclient.any_instance.expects(:head).with(instance_of(HTTPI::Request))
105
+
106
+ client.head "http://example.com"
107
+ end
108
+ end
109
+
110
+ describe ".head(url, adapter)" do
111
+ it "executes a HEAD request using the given adapter" do
112
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
113
+ curb.any_instance.expects(:head).with(instance_of(HTTPI::Request))
114
+
115
+ client.head "http://example.com", :curb
116
+ end
117
+ end
118
+
119
+ describe ".put(request)" do
120
+ it "executes a PUT request using the default adapter" do
121
+ request = HTTPI::Request.new
122
+ httpclient.any_instance.expects(:put).with(request)
123
+
124
+ client.put request
125
+ end
126
+ end
127
+
128
+ describe ".put(request, adapter)" do
129
+ it "executes a PUT request using the given adapter" do
130
+ request = HTTPI::Request.new
131
+ curb.any_instance.expects(:put).with(request)
132
+
133
+ client.put request, :curb
134
+ end
135
+ end
136
+
137
+ describe ".put(url, body)" do
138
+ it "executes a PUT request using the default adapter" do
139
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
140
+ HTTPI::Request.any_instance.expects(:body=).with("<some>xml</some>")
141
+ httpclient.any_instance.expects(:put).with(instance_of(HTTPI::Request))
142
+
143
+ client.put "http://example.com", "<some>xml</some>"
144
+ end
145
+ end
146
+
147
+ describe ".put(url, body, adapter)" do
148
+ it "executes a PUT request using the given adapter" do
149
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
150
+ HTTPI::Request.any_instance.expects(:body=).with("<some>xml</some>")
151
+ curb.any_instance.expects(:put).with(instance_of(HTTPI::Request))
152
+
153
+ client.put "http://example.com", "<some>xml</some>", :curb
154
+ end
155
+ end
156
+
157
+ describe ".delete(request)" do
158
+ it "executes a DELETE request using the default adapter" do
159
+ request = HTTPI::Request.new
160
+ httpclient.any_instance.expects(:delete).with(request)
161
+
162
+ client.delete request
163
+ end
164
+ end
165
+
166
+ describe ".delete(request, adapter)" do
167
+ it "executes a DELETE request using the given adapter" do
168
+ request = HTTPI::Request.new
169
+ curb.any_instance.expects(:delete).with(request)
170
+
171
+ client.delete request, :curb
172
+ end
173
+ end
174
+
175
+ describe ".delete(url)" do
176
+ it "executes a DELETE request using the default adapter" do
177
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
178
+ httpclient.any_instance.expects(:delete).with(instance_of(HTTPI::Request))
179
+
180
+ client.delete "http://example.com"
181
+ end
182
+ end
183
+
184
+ describe ".delete(url, adapter)" do
185
+ it "executes a DELETE request using the given adapter" do
186
+ HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
187
+ curb.any_instance.expects(:delete).with(instance_of(HTTPI::Request))
188
+
189
+ client.delete "http://example.com", :curb
190
+ end
191
+ end
192
+
193
+ describe ".request" do
194
+ it "raises an ArgumentError in case of an invalid request method" do
195
+ expect { client.request :invalid, HTTPI::Request.new }.to raise_error(ArgumentError)
196
+ end
197
+ end
198
+
199
+ describe ".adapter=" do
200
+ it "sets the default adapter to use" do
201
+ HTTPI::Adapter.expects(:use=).with(:net_http)
202
+ HTTPI.adapter = :net_http
203
+ end
204
+ end
205
+
206
+ HTTPI::REQUEST_METHODS.each do |method|
207
+ describe ".request(#{method}, request, adapter)" do
208
+ it "delegates to the .#{method} method" do
209
+ HTTPI.expects(method)
210
+ client.request method, HTTPI::Request.new
211
+ end
212
+ end
213
+
214
+ describe ".#{method}" do
215
+ let(:request) { HTTPI::Request.new :url => "http://example.com" }
216
+
217
+ it "raises an ArgumentError in case of an invalid adapter" do
218
+ expect { client.request method, request, :invalid }.to raise_error(ArgumentError)
219
+ end
220
+
221
+ it "raises an ArgumentError in case of an invalid request" do
222
+ expect { client.request method, "invalid" }.to raise_error(ArgumentError)
223
+ end
224
+
225
+ HTTPI::Adapter::ADAPTERS.each do |adapter, opts|
226
+ client_class = {
227
+ :httpclient => lambda { HTTPClient },
228
+ :curb => lambda { Curl::Easy },
229
+ :net_http => lambda { Net::HTTP }
230
+ }
231
+
232
+ context "using #{adapter}" do
233
+ before { opts[:class].any_instance.expects(method) }
234
+
235
+ it "logs that we're executing a request" do
236
+ HTTPI.expects(:log).with(:debug, "HTTPI executes HTTP #{method.to_s.upcase} using the #{adapter} adapter")
237
+ client.request method, request, adapter
238
+ end
239
+
240
+ it "yields the HTTP client instance used for the request" do
241
+ block = lambda { |http| http.be_a(client_class[adapter].call) }
242
+ client.request(method, request, adapter, &block)
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ context "(with reset)" do
250
+ before { HTTPI.reset_config! }
251
+
252
+ after do
253
+ HTTPI.reset_config!
254
+ HTTPI.log = false # disable for specs
255
+ end
256
+
257
+ describe ".log" do
258
+ it "defaults to true" do
259
+ HTTPI.log?.should be_true
260
+ end
261
+ end
262
+
263
+ describe ".logger" do
264
+ it "defaults to Logger writing to STDOUT" do
265
+ HTTPI.logger.should be_a(Logger)
266
+ end
267
+ end
268
+
269
+ describe ".log_level" do
270
+ it "defaults to :warn" do
271
+ HTTPI.log_level.should == :warn
272
+ end
273
+ end
274
+
275
+ describe ".log" do
276
+ it "logs the given messages" do
277
+ HTTPI.log_level = :debug
278
+ HTTPI.logger.expects(:debug).with("Log this")
279
+ HTTPI.log "Log", "this"
280
+ end
281
+ end
282
+ end
283
+
284
+ end
@@ -0,0 +1,135 @@
1
+ require "spec_helper"
2
+ require "httpi/request"
3
+
4
+ describe HTTPI::Request do
5
+ let(:request) { HTTPI::Request.new }
6
+
7
+ describe ".new" do
8
+ it "accepts a url" do
9
+ request = HTTPI::Request.new "http://example.com"
10
+ request.url.should == URI("http://example.com")
11
+ end
12
+
13
+ it "accepts a Hash of accessors to set" do
14
+ request = HTTPI::Request.new :url => "http://example.com", :open_timeout => 30
15
+ request.url.should == URI("http://example.com")
16
+ request.open_timeout.should == 30
17
+ end
18
+ end
19
+
20
+ describe "#url" do
21
+ it "lets you specify the URL to access as a String" do
22
+ request.url = "http://example.com"
23
+ request.url.should == URI("http://example.com")
24
+ end
25
+
26
+ it "also accepts a URI object" do
27
+ request.url = URI("http://example.com")
28
+ request.url.should == URI("http://example.com")
29
+ end
30
+
31
+ it "raises an ArgumentError in case of an invalid url" do
32
+ expect { request.url = "invalid" }.to raise_error(ArgumentError)
33
+ end
34
+ end
35
+
36
+ describe "#proxy" do
37
+ it "lets you specify the proxy URL to use as a String" do
38
+ request.proxy = "http://proxy.example.com"
39
+ request.proxy.should == URI("http://proxy.example.com")
40
+ end
41
+
42
+ it "also accepts a URI object" do
43
+ request.proxy = URI("http://proxy.example.com")
44
+ request.proxy.should == URI("http://proxy.example.com")
45
+ end
46
+
47
+ it "raises an ArgumentError in case of an invalid url" do
48
+ expect { request.proxy = "invalid" }.to raise_error(ArgumentError)
49
+ end
50
+ end
51
+
52
+ describe "#ssl" do
53
+ it "returns false if no request url was specified" do
54
+ request.should_not be_ssl
55
+ end
56
+
57
+ it "returns false if the request url does not start with https" do
58
+ request.url = "http://example.com"
59
+ request.should_not be_ssl
60
+ end
61
+
62
+ it "returns true if the request url starts with https" do
63
+ request.url = "https://example.com"
64
+ request.should be_ssl
65
+ end
66
+
67
+ context "with an explicit value" do
68
+ it "returns the value" do
69
+ request.ssl = true
70
+ request.should be_ssl
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "#headers" do
76
+ it "lets you specify a Hash of HTTP request headers" do
77
+ request.headers = { "Accept-Encoding" => "gzip" }
78
+ request.headers.should == { "Accept-Encoding" => "gzip" }
79
+ end
80
+
81
+ it "defaults to return an empty Hash" do
82
+ request.headers.should == {}
83
+ end
84
+ end
85
+
86
+ describe "#gzip" do
87
+ it "adds the proper 'Accept-Encoding' header" do
88
+ request.gzip
89
+ request.headers["Accept-Encoding"].should == "gzip,deflate"
90
+ end
91
+ end
92
+
93
+ describe "#body" do
94
+ it "lets you specify the HTTP request body" do
95
+ request.body = "<some>xml</some>"
96
+ request.body.should == "<some>xml</some>"
97
+ end
98
+ end
99
+
100
+ describe "#open_timeout" do
101
+ it "lets you specify the open timeout" do
102
+ request.open_timeout = 30
103
+ request.open_timeout.should == 30
104
+ end
105
+ end
106
+
107
+ describe "#read_timeout" do
108
+ it "lets you specify the read timeout" do
109
+ request.read_timeout = 45
110
+ request.read_timeout.should == 45
111
+ end
112
+ end
113
+
114
+ describe "#auth" do
115
+ it "returns the authentication object" do
116
+ request.auth.should be_an(HTTPI::Auth::Config)
117
+ end
118
+
119
+ it "memoizes the authentication object" do
120
+ request.auth.should equal(request.auth)
121
+ end
122
+ end
123
+
124
+ describe "#auth?" do
125
+ it "returns true when auth credentials are specified" do
126
+ request.auth.basic "username", "password"
127
+ request.auth?.should be_true
128
+ end
129
+
130
+ it "returns false otherwise" do
131
+ request.auth?.should be_false
132
+ end
133
+ end
134
+
135
+ end