httpi 0.5.0 → 0.6.0

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.
@@ -1,4 +1,5 @@
1
1
  require "uri"
2
+ require "httpi/auth/config"
2
3
 
3
4
  module HTTPI
4
5
 
@@ -7,17 +8,16 @@ module HTTPI
7
8
  # Represents an HTTP request and contains various methods for customizing that request.
8
9
  class Request
9
10
 
10
- # Request accessor methods.
11
- ACCESSORS = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout]
11
+ # Available attribute writers.
12
+ ATTRIBUTES = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout]
12
13
 
13
- # Request authentication methods.
14
- AUTHENTICATION = [:basic_auth, :digest_auth]
15
-
16
- # Accepts a Hash of +options+ which may contain any number of ACCESSORS and/or
17
- # AUTHENTICATION credentials to set.
18
- def initialize(options = {})
19
- assign_accessors options
20
- assign_authentication options
14
+ # Accepts a Hash of +args+ to mass assign attributes and authentication credentials.
15
+ def initialize(args = {})
16
+ if args.kind_of? String
17
+ self.url = args
18
+ elsif args.kind_of?(Hash) && !args.empty?
19
+ mass_assign args
20
+ end
21
21
  end
22
22
 
23
23
  # Sets the +url+ to access. Raises an +ArgumentError+ unless the +url+ is valid.
@@ -36,6 +36,15 @@ module HTTPI
36
36
  # Returns the +proxy+ to use.
37
37
  attr_reader :proxy
38
38
 
39
+ # Returns whether to use SSL.
40
+ def ssl?
41
+ return @ssl unless @ssl.nil?
42
+ !!(url.to_s =~ /^https/)
43
+ end
44
+
45
+ # Sets whether to use SSL.
46
+ attr_writer :ssl
47
+
39
48
  # Returns a Hash of HTTP headers. Defaults to return an empty Hash.
40
49
  def headers
41
50
  @headers ||= {}
@@ -49,55 +58,30 @@ module HTTPI
49
58
  headers["Accept-Encoding"] = "gzip,deflate"
50
59
  end
51
60
 
52
- attr_accessor :body, :open_timeout, :read_timeout, :auth_type
53
-
54
- # Returns whether any authentication credentials were specified.
55
- def auth?
56
- !!auth_type
57
- end
58
-
59
- # Shortcut method for returning the credentials for the authentication specified.
60
- # Return +nil+ unless any authentication credentials were specified.
61
- def credentials
62
- return unless auth?
63
- send "#{auth_type}_auth"
64
- end
61
+ attr_accessor :body, :open_timeout, :read_timeout
65
62
 
66
- # Sets the HTTP basic auth credentials. Accepts an Array or two arguments for the
67
- # +username+ and +password+. Resets the credentials when +nil+ is passed and returns
68
- # an Array of credentials when no +args+ where given.
69
- def basic_auth(*args)
70
- self.auth_type = :basic
71
- @basic_auth = extract_credentials @basic_auth, args.flatten
63
+ # Returns the <tt>HTTPI::Authentication</tt> object.
64
+ def auth
65
+ @auth ||= Auth::Config.new
72
66
  end
73
67
 
74
- # Sets the HTTP digest auth credentials. Accepts an Array or two arguments for the
75
- # +username+ and +password+. Resets the credentials when +nil+ is passed and returns
76
- # an Array of credentials when no +args+ where given.
77
- def digest_auth(*args)
78
- self.auth_type = :digest
79
- @digest_auth = extract_credentials @digest_auth, args.flatten
68
+ # Returns whether any authentication credentials were specified.
69
+ def auth?
70
+ !!auth.type
80
71
  end
81
72
 
82
- private
83
-
84
- def assign_accessors(options)
85
- ACCESSORS.each { |a| send("#{a}=", options[a]) if options[a] }
86
- end
87
-
88
- def assign_authentication(options)
89
- AUTHENTICATION.each { |c| send(c, options[c]) if options[c] }
73
+ # Expects a Hash of +args+ to assign.
74
+ def mass_assign(args)
75
+ ATTRIBUTES.each { |key| send("#{key}=", args[key]) if args[key] }
90
76
  end
91
77
 
78
+ private
79
+
80
+ # Expects a +url+, validates its validity and returns a +URI+ object.
92
81
  def normalize_url!(url)
93
82
  raise ArgumentError, "Invalid URL: #{url}" unless url.to_s =~ /^http/
94
83
  url.kind_of?(URI) ? url : URI(url)
95
84
  end
96
85
 
97
- def extract_credentials(credentials, args)
98
- return unless args.empty? || args.first
99
- args[1] ? args[0, 2] : credentials
100
- end
101
-
102
86
  end
103
87
  end
@@ -1,5 +1,5 @@
1
1
  module HTTPI
2
2
 
3
- VERSION = "0.5.0"
3
+ VERSION = "0.6.0"
4
4
 
5
5
  end
@@ -0,0 +1,16 @@
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==
16
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXQIBAAKBgQC8mJqiMgVABsVzNeQGaPGnGtr0ttCbRUgRIVKXy4FKOYb+CYIH
3
+ AqDw73g/e0CMM0KUL58SoEsTfsofip7vrLDu6mBGu4/mNDNQQvXIJpW0D8OiqBoL
4
+ FnLtWEHYDd/vVnDqRA+3cE4wTrx+caxNfrnH1cBrAIbMaYlKT9nrC+aXUwIDAQAB
5
+ AoGBAKjrGh1KJg+pwPInA5yGJGMil5h1obRgwmKtcPeKi7u6eOFSDMdQoGwMYKyj
6
+ LTYlt21Yleat8XB9sHW9yAstpq5dU8Id2A4wfbJeaBYpek7u5+QwBENO4UrnulTk
7
+ W0d+jECBVYECn8wCStxfoFcQQRhlGrsOn05379cD8e1odMOJAkEA3o/7CsgXqahG
8
+ 7L1HaWYtKnpFfTS+EQgdGvSahOolByAKTtMA2TUBU1FdlCk+ggWBGorqmWON5Qnm
9
+ 7UDHjOasZQJBANjuPOqa9ubqHccGwHec+72pQz6q5e8f1gf1XPn7EEuXsBzYiMMH
10
+ qEa8zpfF0TmhQ0oWN75Cq709gfVVBfx/bVcCQHan1HN/Ef6FlKqKjxQGQXYwEfQa
11
+ tmpmJP5GAktyeaM+1cAIhp9GvxooeveOtaCkRpxcC48ToIbHrLI4oyrfoHECQQC6
12
+ bAHtmz6TMp5ka2j7Yez1EIC5WiQ/WxyTukgsi5V1YOX35B2jfPEf2SGxTE6BOBSb
13
+ lnxRBPqRpkoIiwiZ9OgBAkBOWKBuHXmXM6wr+0p4KQ/DOeStZiBxUT8rYbX/i1BI
14
+ /9Xo48KNerTx7qoDK+jIslDrilahvcwUz0fuVV7rHy/X
15
+ -----END RSA PRIVATE KEY-----
@@ -24,8 +24,7 @@ describe HTTPI::Adapter::Curb do
24
24
  end
25
25
 
26
26
  it "should return a valid HTTPI::Response" do
27
- request = HTTPI::Request.new :url => "http://example.com"
28
- adapter.get(request).should match_response(:body => Fixture.xml)
27
+ adapter.get(basic_request).should match_response(:body => Fixture.xml)
29
28
  end
30
29
  end
31
30
 
@@ -38,8 +37,7 @@ describe HTTPI::Adapter::Curb do
38
37
  end
39
38
 
40
39
  it "should return a valid HTTPI::Response" do
41
- request = HTTPI::Request.new :url => "http://example.com"
42
- adapter.post(request).should match_response(:body => Fixture.xml)
40
+ adapter.post(basic_request).should match_response(:body => Fixture.xml)
43
41
  end
44
42
  end
45
43
 
@@ -52,8 +50,7 @@ describe HTTPI::Adapter::Curb do
52
50
  end
53
51
 
54
52
  it "should return a valid HTTPI::Response" do
55
- request = HTTPI::Request.new :url => "http://example.com"
56
- adapter.head(request).should match_response(:body => Fixture.xml)
53
+ adapter.head(basic_request).should match_response(:body => Fixture.xml)
57
54
  end
58
55
  end
59
56
 
@@ -66,8 +63,7 @@ describe HTTPI::Adapter::Curb do
66
63
  end
67
64
 
68
65
  it "should return a valid HTTPI::Response" do
69
- request = HTTPI::Request.new :url => "http://example.com"
70
- adapter.put(request).should match_response(:body => Fixture.xml)
66
+ adapter.put(basic_request).should match_response(:body => Fixture.xml)
71
67
  end
72
68
  end
73
69
 
@@ -80,9 +76,139 @@ describe HTTPI::Adapter::Curb do
80
76
  end
81
77
 
82
78
  it "should return a valid HTTPI::Response" do
83
- request = HTTPI::Request.new :url => "http://example.com"
84
- adapter.delete(request).should match_response(:body => "")
79
+ adapter.delete(basic_request).should match_response(:body => "")
85
80
  end
86
81
  end
87
82
 
83
+ describe "settings:" do
84
+ before { curb.stubs(:http_get) }
85
+
86
+ describe "url" do
87
+ it "should always set the request url" do
88
+ curb.expects(:url=).with(basic_request.url.to_s)
89
+ adapter.get(basic_request)
90
+ end
91
+ end
92
+
93
+ describe "proxy_url" do
94
+ it "should not be set if not specified" do
95
+ curb.expects(:proxy_url=).never
96
+ adapter.get(basic_request)
97
+ end
98
+
99
+ it "should be set if specified" do
100
+ request = basic_request { |request| request.proxy = "http://proxy.example.com" }
101
+
102
+ curb.expects(:proxy_url=).with(request.proxy.to_s)
103
+ adapter.get(request)
104
+ end
105
+ end
106
+
107
+ describe "timeout" do
108
+ it "should not be set if not specified" do
109
+ curb.expects(:timeout=).never
110
+ adapter.get(basic_request)
111
+ end
112
+
113
+ it "should be set if specified" do
114
+ request = basic_request { |request| request.read_timeout = 30 }
115
+
116
+ curb.expects(:timeout=).with(30)
117
+ adapter.get(request)
118
+ end
119
+ end
120
+
121
+ describe "connect_timeout" do
122
+ it "should not be set if not specified" do
123
+ curb.expects(:connect_timeout=).never
124
+ adapter.get(basic_request)
125
+ end
126
+
127
+ it "should be set if specified" do
128
+ request = basic_request { |request| request.open_timeout = 30 }
129
+
130
+ curb.expects(:connect_timeout=).with(30)
131
+ adapter.get(request)
132
+ end
133
+ end
134
+
135
+ describe "headers" do
136
+ it "should always be set" do
137
+ curb.expects(:headers=).with({})
138
+ adapter.get(basic_request)
139
+ end
140
+ end
141
+
142
+ describe "verbose" do
143
+ it "should always be set to false" do
144
+ curb.expects(:verbose=).with(false)
145
+ adapter.get(basic_request)
146
+ end
147
+ end
148
+
149
+ describe "http_auth_types" do
150
+ it "should be set to :basic for HTTP basic auth" do
151
+ request = basic_request { |request| request.auth.basic "username", "password" }
152
+
153
+ curb.expects(:http_auth_types=).with(:basic)
154
+ adapter.get(request)
155
+ end
156
+
157
+ it "should be set to :digest for HTTP digest auth" do
158
+ request = basic_request { |request| request.auth.digest "username", "password" }
159
+
160
+ curb.expects(:http_auth_types=).with(:digest)
161
+ adapter.get(request)
162
+ end
163
+ end
164
+
165
+ describe "username and password" do
166
+ it "should be set for HTTP basic auth" do
167
+ request = basic_request { |request| request.auth.basic "username", "password" }
168
+
169
+ curb.expects(:username=).with("username")
170
+ curb.expects(:password=).with("password")
171
+ adapter.get(request)
172
+ end
173
+
174
+ it "should be set for HTTP digest auth" do
175
+ request = basic_request { |request| request.auth.digest "username", "password" }
176
+
177
+ curb.expects(:username=).with("username")
178
+ curb.expects(:password=).with("password")
179
+ adapter.get(request)
180
+ end
181
+ end
182
+
183
+ context "(for SSL client auth)" do
184
+ let(:ssl_auth_request) do
185
+ basic_request do |request|
186
+ request.auth.ssl.cert_key_file = "spec/fixtures/client_key.pem"
187
+ request.auth.ssl.cert_file = "spec/fixtures/client_cert.pem"
188
+ end
189
+ end
190
+
191
+ it "cert_key, cert and ssl_verify_peer should be set" do
192
+ curb.expects(:cert_key=).with(ssl_auth_request.auth.ssl.cert_key_file)
193
+ curb.expects(:cert=).with(ssl_auth_request.auth.ssl.cert_file)
194
+ curb.expects(:ssl_verify_peer=).with(true)
195
+
196
+ adapter.get(ssl_auth_request)
197
+ end
198
+
199
+ it "should set the cacert if specified" do
200
+ ssl_auth_request.auth.ssl.ca_cert_file = "spec/fixtures/client_cert.pem"
201
+ curb.expects(:cacert=).with(ssl_auth_request.auth.ssl.ca_cert_file)
202
+
203
+ adapter.get(ssl_auth_request)
204
+ end
205
+ end
206
+ end
207
+
208
+ def basic_request
209
+ request = HTTPI::Request.new :url => "http://example.com"
210
+ yield request if block_given?
211
+ request
212
+ end
213
+
88
214
  end
@@ -7,6 +7,7 @@ require "httpclient"
7
7
  describe HTTPI::Adapter::HTTPClient do
8
8
  let(:adapter) { HTTPI::Adapter::HTTPClient.new }
9
9
  let(:httpclient) { HTTPClient.any_instance }
10
+ let(:ssl_config) { HTTPClient::SSLConfig.any_instance }
10
11
 
11
12
  describe ".new" do
12
13
  it "should require the HTTPClient gem" do
@@ -16,63 +17,128 @@ describe HTTPI::Adapter::HTTPClient do
16
17
  end
17
18
 
18
19
  describe "#get" do
19
- before do
20
- @request = HTTPI::Request.new :url => "http://example.com"
21
- response = HTTP::Message.new_response Fixture.xml
22
- httpclient.expects(:get).with(@request.url, nil, @request.headers).returns(response)
23
- end
24
-
25
20
  it "should return a valid HTTPI::Response" do
26
- adapter.get(@request).should match_response(:body => Fixture.xml)
21
+ httpclient.expects(:get).with(basic_request.url, nil, basic_request.headers).returns(http_message)
22
+ adapter.get(basic_request).should match_response(:body => Fixture.xml)
27
23
  end
28
24
  end
29
25
 
30
26
  describe "#post" do
31
- before do
32
- @request = HTTPI::Request.new :url => "http://example.com", :body => Fixture.xml
33
- response = HTTP::Message.new_response Fixture.xml
34
- httpclient.expects(:post).with(@request.url, @request.body, @request.headers).returns(response)
35
- end
36
-
37
27
  it "should return a valid HTTPI::Response" do
38
- adapter.post(@request).should match_response(:body => Fixture.xml)
28
+ request = HTTPI::Request.new :url => "http://example.com", :body => Fixture.xml
29
+ httpclient.expects(:post).with(request.url, request.body, request.headers).returns(http_message)
30
+
31
+ adapter.post(request).should match_response(:body => Fixture.xml)
39
32
  end
40
33
  end
41
34
 
42
35
  describe "#head" do
43
- before do
44
- @request = HTTPI::Request.new :url => "http://example.com"
45
- response = HTTP::Message.new_response Fixture.xml
46
- httpclient.expects(:head).with(@request.url, nil, @request.headers).returns(response)
47
- end
48
-
49
36
  it "should return a valid HTTPI::Response" do
50
- adapter.head(@request).should match_response(:body => Fixture.xml)
37
+ httpclient.expects(:head).with(basic_request.url, nil, basic_request.headers).returns(http_message)
38
+ adapter.head(basic_request).should match_response(:body => Fixture.xml)
51
39
  end
52
40
  end
53
41
 
54
42
  describe "#put" do
55
- before do
56
- @request = HTTPI::Request.new :url => "http://example.com", :body => Fixture.xml
57
- response = HTTP::Message.new_response Fixture.xml
58
- httpclient.expects(:put).with(@request.url, @request.body, @request.headers).returns(response)
43
+ it "should return a valid HTTPI::Response" do
44
+ request = HTTPI::Request.new :url => "http://example.com", :body => Fixture.xml
45
+ httpclient.expects(:put).with(request.url, request.body, request.headers).returns(http_message)
46
+
47
+ adapter.put(request).should match_response(:body => Fixture.xml)
59
48
  end
49
+ end
60
50
 
51
+ describe "#delete" do
61
52
  it "should return a valid HTTPI::Response" do
62
- adapter.put(@request).should match_response(:body => Fixture.xml)
53
+ httpclient.expects(:delete).with(basic_request.url, basic_request.headers).returns(http_message(""))
54
+ adapter.delete(basic_request).should match_response(:body => "")
63
55
  end
64
56
  end
65
57
 
66
- describe "#delete" do
67
- before do
68
- @request = HTTPI::Request.new :url => "http://example.com"
69
- response = HTTP::Message.new_response ""
70
- httpclient.expects(:delete).with(@request.url, @request.headers).returns(response)
58
+ describe "settings:" do
59
+ before { httpclient.stubs(:get).returns(http_message) }
60
+
61
+ describe "proxy" do
62
+ it "should have specs"
71
63
  end
72
64
 
73
- it "should return a valid HTTPI::Response" do
74
- adapter.delete(@request).should match_response(:body => "")
65
+ describe "connect_timeout" do
66
+ it "should not be set if not specified" do
67
+ httpclient.expects(:connect_timeout=).never
68
+ adapter.get(basic_request)
69
+ end
70
+
71
+ it "should be set if specified" do
72
+ request = basic_request { |request| request.open_timeout = 30 }
73
+
74
+ httpclient.expects(:connect_timeout=).with(30)
75
+ adapter.get(request)
76
+ end
75
77
  end
78
+
79
+ describe "receive_timeout" do
80
+ it "should not be set if not specified" do
81
+ httpclient.expects(:receive_timeout=).never
82
+ adapter.get(basic_request)
83
+ end
84
+
85
+ it "should be set if specified" do
86
+ request = basic_request { |request| request.read_timeout = 30 }
87
+
88
+ httpclient.expects(:receive_timeout=).with(30)
89
+ adapter.get(request)
90
+ end
91
+ end
92
+
93
+ describe "set_auth" do
94
+ it "should be set for HTTP basic auth" do
95
+ request = basic_request { |request| request.auth.basic "username", "password" }
96
+
97
+ httpclient.expects(:set_auth).with(request.url, *request.auth.credentials)
98
+ adapter.get(request)
99
+ end
100
+
101
+ it "should be set for HTTP digest auth" do
102
+ request = basic_request { |request| request.auth.digest "username", "password" }
103
+
104
+ httpclient.expects(:set_auth).with(request.url, *request.auth.credentials)
105
+ adapter.get(request)
106
+ end
107
+ end
108
+
109
+ context "(for SSL client auth)" do
110
+ let(:ssl_auth_request) do
111
+ basic_request do |request|
112
+ request.auth.ssl.cert_key_file = "spec/fixtures/client_key.pem"
113
+ request.auth.ssl.cert_file = "spec/fixtures/client_cert.pem"
114
+ end
115
+ end
116
+
117
+ it "client_cert, client_key and verify_mode should be set" do
118
+ ssl_config.expects(:client_cert=).with(ssl_auth_request.auth.ssl.cert)
119
+ ssl_config.expects(:client_key=).with(ssl_auth_request.auth.ssl.cert_key)
120
+ ssl_config.expects(:verify_mode=).with(ssl_auth_request.auth.ssl.openssl_verify_mode)
121
+
122
+ adapter.get(ssl_auth_request)
123
+ end
124
+
125
+ it "should set the client_ca if specified" do
126
+ ssl_auth_request.auth.ssl.ca_cert_file = "spec/fixtures/client_cert.pem"
127
+ ssl_config.expects(:client_ca=).with(ssl_auth_request.auth.ssl.ca_cert)
128
+
129
+ adapter.get(ssl_auth_request)
130
+ end
131
+ end
132
+ end
133
+
134
+ def http_message(body = Fixture.xml)
135
+ HTTP::Message.new_response body
136
+ end
137
+
138
+ def basic_request
139
+ request = HTTPI::Request.new "http://example.com"
140
+ yield request if block_given?
141
+ request
76
142
  end
77
143
 
78
144
  end