httpi 0.3.0 → 0.4.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.
- data/.autotest +5 -0
- data/Gemfile.lock +1 -1
- data/LICENSE +20 -0
- data/README.md +31 -21
- data/Rakefile +7 -0
- data/lib/httpi.rb +98 -54
- data/lib/httpi/adapter/curb.rb +36 -10
- data/lib/httpi/adapter/httpclient.rb +40 -7
- data/lib/httpi/request.rb +23 -2
- data/lib/httpi/version.rb +1 -1
- data/spec/httpi/adapter/curb_spec.rb +41 -2
- data/spec/httpi/adapter/httpclient_spec.rb +35 -2
- data/spec/httpi/httpi_spec.rb +132 -17
- data/spec/httpi/request_spec.rb +60 -1
- data/spec/integration/request_spec.rb +68 -0
- metadata +7 -4
data/.autotest
ADDED
data/Gemfile.lock
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Daniel Harrington
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -3,6 +3,8 @@ HTTPI
|
|
3
3
|
|
4
4
|
HTTPI provides a common interface for Ruby HTTP libraries.
|
5
5
|
|
6
|
+
[Feedback](http://httpi.uservoice.com) | [Bugs](http://github.com/rubiii/httpi/issues) | [Docs](http://rubydoc.info/gems/httpi)
|
7
|
+
|
6
8
|
Installation
|
7
9
|
------------
|
8
10
|
|
@@ -13,12 +15,12 @@ The gem is available through [Rubygems](http://rubygems.org/gems/httpi) and can
|
|
13
15
|
Some examples
|
14
16
|
-------------
|
15
17
|
|
16
|
-
|
18
|
+
Executing a POST request with the most basic request object:
|
17
19
|
|
18
20
|
request = HTTPI::Request.new :url => "http://example.com"
|
19
21
|
HTTPI.get request
|
20
22
|
|
21
|
-
|
23
|
+
Here's a POST request with a request object:
|
22
24
|
|
23
25
|
request = HTTPI::Request.new
|
24
26
|
request.url = "http://post.example.com"
|
@@ -34,19 +36,19 @@ And a GET request using HTTP basic auth and the Curb adapter:
|
|
34
36
|
|
35
37
|
HTTPI.get request, :curb
|
36
38
|
|
37
|
-
HTTPI also comes with some shortcuts. This executes a
|
39
|
+
HTTPI also comes with some shortcuts. This executes a PUT request:
|
38
40
|
|
39
|
-
HTTPI.
|
41
|
+
HTTPI.put "http://example.com", "<some>xml</some>"
|
40
42
|
|
41
|
-
And
|
43
|
+
And this executes a DELETE request:
|
42
44
|
|
43
|
-
HTTPI.
|
45
|
+
HTTPI.delete "http://example.com"
|
44
46
|
|
45
47
|
HTTPI
|
46
48
|
-------------
|
47
49
|
|
48
|
-
The `HTTPI` module uses one of the available adapters to execute HTTP requests.
|
49
|
-
It
|
50
|
+
The `HTTPI` module uses one of the available adapters to execute HTTP requests.
|
51
|
+
It supports GET, POST, HEAD, PUT and DELETE requests:
|
50
52
|
|
51
53
|
### GET
|
52
54
|
|
@@ -58,6 +60,21 @@ It currently supports GET and POST requests:
|
|
58
60
|
.post(request, adapter = nil)
|
59
61
|
.post(url, body, adapter = nil)
|
60
62
|
|
63
|
+
### HEAD
|
64
|
+
|
65
|
+
.head(request, adapter = nil)
|
66
|
+
.head(url, adapter = nil)
|
67
|
+
|
68
|
+
### PUT
|
69
|
+
|
70
|
+
.put(request, adapter = nil)
|
71
|
+
.put(url, body, adapter = nil)
|
72
|
+
|
73
|
+
### DELETE
|
74
|
+
|
75
|
+
.delete(request, adapter = nil)
|
76
|
+
.delete(url, adapter = nil)
|
77
|
+
|
61
78
|
### Notice
|
62
79
|
|
63
80
|
* You can specify the adapter to use per request
|
@@ -72,10 +89,6 @@ by your adapter in a block:
|
|
72
89
|
http.use_ssl = true # Curb example
|
73
90
|
end
|
74
91
|
|
75
|
-
### TODO
|
76
|
-
|
77
|
-
* Add support for HEAD, PUT and DELETE requests
|
78
|
-
|
79
92
|
HTTPI::Request
|
80
93
|
--------------
|
81
94
|
|
@@ -91,17 +104,18 @@ It represents an HTTP request and lets you customize various settings through th
|
|
91
104
|
|
92
105
|
It also contains methods for setting up authentication:
|
93
106
|
|
94
|
-
#basic_auth(username, password)
|
107
|
+
#basic_auth(username, password) # HTTP basic auth credentials
|
108
|
+
#digest_auth(username, password) # HTTP digest auth credentials
|
95
109
|
|
96
110
|
### TODO
|
97
111
|
|
98
|
-
* Add support for HTTP digest authentication
|
99
112
|
* Add support for SSL client authentication
|
113
|
+
* Add support for NTLM authentication
|
100
114
|
|
101
115
|
HTTPI::Adapter
|
102
116
|
--------------
|
103
117
|
|
104
|
-
HTTPI uses adapters to support multiple HTTP libraries.
|
118
|
+
HTTPI uses adapters to support multiple HTTP libraries.
|
105
119
|
It currently contains adapters for:
|
106
120
|
|
107
121
|
* [httpclient](http://rubygems.org/gems/httpclient) ~> 2.1.5
|
@@ -109,16 +123,12 @@ It currently contains adapters for:
|
|
109
123
|
|
110
124
|
By default, HTTPI uses the `HTTPClient`. But changing the default is fairly easy:
|
111
125
|
|
112
|
-
HTTPI::Adapter.use = :curb
|
113
|
-
|
114
|
-
You can find a list of supported adapters via:
|
115
|
-
|
116
|
-
HTTPI::Adapter.adapters # returns a Hash of supported adapters
|
126
|
+
HTTPI::Adapter.use = :curb # or :httpclient
|
117
127
|
|
118
128
|
HTTPI::Response
|
119
129
|
---------------
|
120
130
|
|
121
|
-
As mentioned before, every request method return an `HTTPI::Response`.
|
131
|
+
As mentioned before, every request method return an `HTTPI::Response`.
|
122
132
|
It contains the response code, headers and body.
|
123
133
|
|
124
134
|
response = HTTPI.get request
|
data/Rakefile
CHANGED
@@ -29,6 +29,13 @@ begin
|
|
29
29
|
require "rspec/core/rake_task"
|
30
30
|
|
31
31
|
RSpec::Core::RakeTask.new do |t|
|
32
|
+
t.pattern = "spec/httpi/*_spec.rb"
|
33
|
+
t.rspec_opts = %w(-fd -c)
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Run RSpec integration examples"
|
37
|
+
RSpec::Core::RakeTask.new "spec:integration" do |t|
|
38
|
+
t.pattern = "spec/integration/*_spec.rb"
|
32
39
|
t.rspec_opts = %w(-fd -c)
|
33
40
|
end
|
34
41
|
rescue LoadError
|
data/lib/httpi.rb
CHANGED
@@ -5,33 +5,73 @@ require "httpi/adapter"
|
|
5
5
|
# = HTTPI
|
6
6
|
#
|
7
7
|
# Executes HTTP requests using a predefined adapter.
|
8
|
+
# All request methods accept an <tt>HTTPI::Request</tt> and an optional adapter.
|
9
|
+
# They may also offer shortcut methods for executing basic requests.
|
10
|
+
# Also they all return an <tt>HTTPI::Response</tt>.
|
11
|
+
#
|
12
|
+
# == GET
|
13
|
+
#
|
14
|
+
# request = HTTPI::Request.new :url => "http://example.com"
|
15
|
+
# HTTPI.get request, :httpclient
|
16
|
+
#
|
17
|
+
# === Shortcuts
|
18
|
+
#
|
19
|
+
# HTTPI.get "http://example.com", :curb
|
20
|
+
#
|
21
|
+
# == POST
|
22
|
+
#
|
23
|
+
# request = HTTPI::Request.new
|
24
|
+
# request.url = "http://example.com"
|
25
|
+
# request.body = "<some>xml</some>"
|
26
|
+
#
|
27
|
+
# HTTPI.post request, :httpclient
|
28
|
+
#
|
29
|
+
# === Shortcuts
|
30
|
+
#
|
31
|
+
# HTTPI.post "http://example.com", "<some>xml</some>", :curb
|
32
|
+
#
|
33
|
+
# == HEAD
|
34
|
+
#
|
35
|
+
# request = HTTPI::Request.new :url => "http://example.com"
|
36
|
+
# HTTPI.head request, :httpclient
|
37
|
+
#
|
38
|
+
# === Shortcuts
|
39
|
+
#
|
40
|
+
# HTTPI.head "http://example.com", :curb
|
41
|
+
#
|
42
|
+
# == PUT
|
43
|
+
#
|
44
|
+
# request = HTTPI::Request.new
|
45
|
+
# request.url = "http://example.com"
|
46
|
+
# request.body = "<some>xml</some>"
|
47
|
+
#
|
48
|
+
# HTTPI.put request, :httpclient
|
49
|
+
#
|
50
|
+
# === Shortcuts
|
51
|
+
#
|
52
|
+
# HTTPI.put "http://example.com", "<some>xml</some>", :curb
|
53
|
+
#
|
54
|
+
# == DELETE
|
55
|
+
#
|
56
|
+
# request = HTTPI::Request.new :url => "http://example.com"
|
57
|
+
# HTTPI.delete request, :httpclient
|
58
|
+
#
|
59
|
+
# === Shortcuts
|
60
|
+
#
|
61
|
+
# HTTPI.delete "http://example.com", :curb
|
62
|
+
#
|
63
|
+
# == More control
|
64
|
+
#
|
65
|
+
# If you need more control over your request, you can access the HTTP client
|
66
|
+
# instance represented by your adapter in a block.
|
67
|
+
#
|
68
|
+
# HTTPI.get request do |http|
|
69
|
+
# http.follow_redirect_count = 3 # HTTPClient example
|
70
|
+
# end
|
8
71
|
module HTTPI
|
9
72
|
class << self
|
10
73
|
|
11
|
-
# Executes an HTTP GET request
|
12
|
-
#
|
13
|
-
# ==== Example
|
14
|
-
#
|
15
|
-
# Accepts an <tt>HTTPI::Request</tt> and an optional adapter:
|
16
|
-
#
|
17
|
-
# request = HTTPI::Request.new :url => "http://example.com"
|
18
|
-
# HTTPI.get request, :httpclient
|
19
|
-
#
|
20
|
-
# ==== Shortcut
|
21
|
-
#
|
22
|
-
# You can also just pass a URL and an optional adapter if you don't
|
23
|
-
# need to configure the request:
|
24
|
-
#
|
25
|
-
# HTTPI.get "http://example.com", :curb
|
26
|
-
#
|
27
|
-
# ==== More control
|
28
|
-
#
|
29
|
-
# If you need more control over the request, you can access the HTTP
|
30
|
-
# client instance represented by your adapter in a block.
|
31
|
-
#
|
32
|
-
# HTTPI.get request do |http|
|
33
|
-
# http.follow_redirect_count = 3 # HTTPClient example
|
34
|
-
# end
|
74
|
+
# Executes an HTTP GET request.
|
35
75
|
def get(request, adapter = nil)
|
36
76
|
request = Request.new :url => request if request.kind_of? String
|
37
77
|
|
@@ -41,35 +81,9 @@ module HTTPI
|
|
41
81
|
end
|
42
82
|
end
|
43
83
|
|
44
|
-
# Executes an HTTP POST request
|
45
|
-
#
|
46
|
-
# ==== Example
|
47
|
-
#
|
48
|
-
# Accepts an <tt>HTTPI::Request</tt> and an optional adapter:
|
49
|
-
#
|
50
|
-
# request = HTTPI::Request.new
|
51
|
-
# request.url = "http://example.com"
|
52
|
-
# request.body = "<some>xml</some>"
|
53
|
-
#
|
54
|
-
# HTTPI.post request, :httpclient
|
55
|
-
#
|
56
|
-
# ==== Shortcut
|
57
|
-
#
|
58
|
-
# You can also just pass a URL, a request body and an optional adapter
|
59
|
-
# if you don't need to configure the request:
|
60
|
-
#
|
61
|
-
# HTTPI.post "http://example.com", "<some>xml</some>", :curb
|
62
|
-
#
|
63
|
-
# ==== More control
|
64
|
-
#
|
65
|
-
# If you need more control over the request, you can access the HTTP
|
66
|
-
# client instance represented by your adapter in a block.
|
67
|
-
#
|
68
|
-
# HTTPI.post request do |http|
|
69
|
-
# http.use_ssl = true # Curb example
|
70
|
-
# end
|
84
|
+
# Executes an HTTP POST request.
|
71
85
|
def post(*args)
|
72
|
-
request, adapter =
|
86
|
+
request, adapter = request_and_adapter_from(args)
|
73
87
|
|
74
88
|
with adapter do |adapter|
|
75
89
|
yield adapter.client if block_given?
|
@@ -77,12 +91,42 @@ module HTTPI
|
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
80
|
-
|
94
|
+
# Executes an HTTP HEAD request.
|
95
|
+
def head(request, adapter = nil)
|
96
|
+
request = Request.new :url => request if request.kind_of? String
|
97
|
+
|
98
|
+
with adapter do |adapter|
|
99
|
+
yield adapter.client if block_given?
|
100
|
+
adapter.head request
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Executes an HTTP PUT request.
|
105
|
+
def put(*args)
|
106
|
+
request, adapter = request_and_adapter_from(args)
|
107
|
+
|
108
|
+
with adapter do |adapter|
|
109
|
+
yield adapter.client if block_given?
|
110
|
+
adapter.put request
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Executes an HTTP DELETE request.
|
115
|
+
def delete(request, adapter = nil)
|
116
|
+
request = Request.new :url => request if request.kind_of? String
|
117
|
+
|
118
|
+
with adapter do |adapter|
|
119
|
+
yield adapter.client if block_given?
|
120
|
+
adapter.delete request
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
81
125
|
|
82
126
|
# Checks whether +args+ contains of an <tt>HTTPI::Request</tt> or a URL
|
83
127
|
# and a request body plus an optional adapter and returns an Array with
|
84
128
|
# an <tt>HTTPI::Request</tt> and (if given) an adapter.
|
85
|
-
def
|
129
|
+
def request_and_adapter_from(args)
|
86
130
|
return args if args[0].kind_of? Request
|
87
131
|
[Request.new(:url => args[0], :body => args[1]), args[2]]
|
88
132
|
end
|
data/lib/httpi/adapter/curb.rb
CHANGED
@@ -9,39 +9,60 @@ module HTTPI
|
|
9
9
|
# http://rubygems.org/gems/curb
|
10
10
|
class Curb
|
11
11
|
|
12
|
+
# Requires the "curb" gem.
|
12
13
|
def initialize
|
13
14
|
require "curb"
|
14
15
|
end
|
15
16
|
|
17
|
+
# Returns a memoized <tt>Curl::Easy</tt> instance.
|
16
18
|
def client
|
17
19
|
@client ||= Curl::Easy.new
|
18
20
|
end
|
19
21
|
|
22
|
+
# Executes an HTTP GET request.
|
23
|
+
# @see HTTPI.get
|
20
24
|
def get(request)
|
21
|
-
|
25
|
+
do_request(request) { |client| client.http_get }
|
22
26
|
end
|
23
27
|
|
28
|
+
# Executes an HTTP POST request.
|
29
|
+
# @see HTTPI.post
|
24
30
|
def post(request)
|
25
|
-
|
31
|
+
do_request(request) { |client, body| client.http_post body }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Executes an HTTP HEAD request.
|
35
|
+
# @see HTTPI.head
|
36
|
+
def head(request)
|
37
|
+
do_request(request) { |client| client.http_head }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Executes an HTTP PUT request.
|
41
|
+
# @see HTTPI.put
|
42
|
+
def put(request)
|
43
|
+
do_request(request) { |client, body| client.http_put body }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Executes an HTTP DELETE request.
|
47
|
+
# @see HTTPI.delete
|
48
|
+
def delete(request)
|
49
|
+
do_request(request) { |client| client.http_delete }
|
26
50
|
end
|
27
51
|
|
28
52
|
private
|
29
53
|
|
30
|
-
def
|
54
|
+
def do_request(request)
|
31
55
|
setup_client request
|
32
56
|
yield client
|
33
57
|
respond_with client
|
34
58
|
end
|
35
59
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
setup_client request
|
40
|
-
yield client, request.body
|
41
|
-
respond_with client
|
60
|
+
def setup_client(request)
|
61
|
+
basic_setup request
|
62
|
+
setup_auth request if request.auth?
|
42
63
|
end
|
43
64
|
|
44
|
-
def
|
65
|
+
def basic_setup(request)
|
45
66
|
client.url = request.url.to_s
|
46
67
|
client.timeout = request.read_timeout
|
47
68
|
client.connect_timeout = request.open_timeout
|
@@ -49,6 +70,11 @@ module HTTPI
|
|
49
70
|
client.verbose = false
|
50
71
|
end
|
51
72
|
|
73
|
+
def setup_auth(request)
|
74
|
+
client.http_auth_types = request.auth_type
|
75
|
+
client.username, client.password = *request.credentials
|
76
|
+
end
|
77
|
+
|
52
78
|
def respond_with(client)
|
53
79
|
Response.new client.response_code, client.headers, client.body_str
|
54
80
|
end
|
@@ -9,44 +9,77 @@ module HTTPI
|
|
9
9
|
# http://rubygems.org/gems/httpclient
|
10
10
|
class HTTPClient
|
11
11
|
|
12
|
+
# Requires the "httpclient" gem.
|
12
13
|
def initialize
|
13
14
|
require "httpclient"
|
14
15
|
end
|
15
16
|
|
17
|
+
# Returns a memoized <tt>HTTPClient</tt> instance.
|
16
18
|
def client
|
17
19
|
@client ||= ::HTTPClient.new
|
18
20
|
end
|
19
21
|
|
22
|
+
# Executes an HTTP GET request.
|
23
|
+
# @see HTTPI.get
|
20
24
|
def get(request)
|
21
|
-
|
25
|
+
do_request request do |client, url, headers|
|
22
26
|
client.get url, nil, headers
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
30
|
+
# Executes an HTTP POST request.
|
31
|
+
# @see HTTPI.post
|
26
32
|
def post(request)
|
27
|
-
|
33
|
+
do_request request do |client, url, headers, body|
|
28
34
|
client.post url, body, headers
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
32
|
-
|
38
|
+
# Executes an HTTP HEAD request.
|
39
|
+
# @see HTTPI.head
|
40
|
+
def head(request)
|
41
|
+
do_request request do |client, url, headers|
|
42
|
+
client.head url, nil, headers
|
43
|
+
end
|
44
|
+
end
|
33
45
|
|
34
|
-
|
35
|
-
|
36
|
-
|
46
|
+
# Executes an HTTP PUT request.
|
47
|
+
# @see HTTPI.put
|
48
|
+
def put(request)
|
49
|
+
do_request request do |client, url, headers, body|
|
50
|
+
client.put url, body, headers
|
51
|
+
end
|
37
52
|
end
|
38
53
|
|
39
|
-
|
54
|
+
# Executes an HTTP DELETE request.
|
55
|
+
# @see HTTPI.delete
|
56
|
+
def delete(request)
|
57
|
+
do_request request do |client, url, headers|
|
58
|
+
client.delete url, headers
|
59
|
+
end
|
60
|
+
end
|
61
|
+
private
|
62
|
+
|
63
|
+
def do_request(request)
|
40
64
|
setup_client request
|
41
65
|
respond_with yield(client, request.url, request.headers, request.body)
|
42
66
|
end
|
43
67
|
|
44
68
|
def setup_client(request)
|
69
|
+
basic_setup request
|
70
|
+
auth_setup request if request.auth?
|
71
|
+
end
|
72
|
+
|
73
|
+
def basic_setup(request)
|
45
74
|
client.proxy = request.proxy if request.proxy
|
46
75
|
client.connect_timeout = request.open_timeout
|
47
76
|
client.receive_timeout = request.read_timeout
|
48
77
|
end
|
49
78
|
|
79
|
+
def auth_setup(request)
|
80
|
+
client.set_auth request.url.to_s, *request.credentials
|
81
|
+
end
|
82
|
+
|
50
83
|
def respond_with(response)
|
51
84
|
Response.new response.code, Hash[response.header.all], response.content
|
52
85
|
end
|
data/lib/httpi/request.rb
CHANGED
@@ -11,7 +11,7 @@ module HTTPI
|
|
11
11
|
ACCESSORS = [:url, :proxy, :headers, :body, :open_timeout, :read_timeout]
|
12
12
|
|
13
13
|
# Request authentication methods.
|
14
|
-
AUTHENTICATION = [:basic_auth]
|
14
|
+
AUTHENTICATION = [:basic_auth, :digest_auth]
|
15
15
|
|
16
16
|
# Accepts a Hash of +options+ which may contain any number of ACCESSORS and/or
|
17
17
|
# AUTHENTICATION credentials to set.
|
@@ -44,15 +44,36 @@ module HTTPI
|
|
44
44
|
# Sets the Hash of HTTP headers.
|
45
45
|
attr_writer :headers
|
46
46
|
|
47
|
-
attr_accessor :body, :open_timeout, :read_timeout
|
47
|
+
attr_accessor :body, :open_timeout, :read_timeout, :auth_type
|
48
|
+
|
49
|
+
# Returns whether any authentication credentials were specified.
|
50
|
+
def auth?
|
51
|
+
!!auth_type
|
52
|
+
end
|
53
|
+
|
54
|
+
# Shortcut method for returning the credentials for the authentication specified.
|
55
|
+
# Return +nil+ unless any authentication credentials were specified.
|
56
|
+
def credentials
|
57
|
+
return unless auth?
|
58
|
+
send "#{auth_type}_auth"
|
59
|
+
end
|
48
60
|
|
49
61
|
# Sets the HTTP basic auth credentials. Accepts an Array or two arguments for the
|
50
62
|
# +username+ and +password+. Resets the credentials when +nil+ is passed and returns
|
51
63
|
# an Array of credentials when no +args+ where given.
|
52
64
|
def basic_auth(*args)
|
65
|
+
self.auth_type = :basic
|
53
66
|
@basic_auth = extract_credentials @basic_auth, args.flatten
|
54
67
|
end
|
55
68
|
|
69
|
+
# Sets the HTTP digest auth credentials. Accepts an Array or two arguments for the
|
70
|
+
# +username+ and +password+. Resets the credentials when +nil+ is passed and returns
|
71
|
+
# an Array of credentials when no +args+ where given.
|
72
|
+
def digest_auth(*args)
|
73
|
+
self.auth_type = :digest
|
74
|
+
@digest_auth = extract_credentials @digest_auth, args.flatten
|
75
|
+
end
|
76
|
+
|
56
77
|
private
|
57
78
|
|
58
79
|
def assign_accessors(options)
|
data/lib/httpi/version.rb
CHANGED
@@ -6,6 +6,7 @@ require "curb"
|
|
6
6
|
|
7
7
|
describe HTTPI::Adapter::Curb do
|
8
8
|
let(:adapter) { HTTPI::Adapter::Curb.new }
|
9
|
+
let(:curb) { Curl::Easy.any_instance }
|
9
10
|
|
10
11
|
describe ".new" do
|
11
12
|
it "should require the Curb gem" do
|
@@ -42,8 +43,46 @@ describe HTTPI::Adapter::Curb do
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
describe "#head" do
|
47
|
+
before do
|
48
|
+
curb.expects(:http_head)
|
49
|
+
curb.expects(:response_code).returns(200)
|
50
|
+
curb.expects(:headers).returns(Hash.new)
|
51
|
+
curb.expects(:body_str).returns(Fixture.xml)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return a valid HTTPI::Response" do
|
55
|
+
request = HTTPI::Request.new :url => "http://example.com"
|
56
|
+
adapter.head(request).should be_a_valid_httpi_response
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#put" do
|
61
|
+
before do
|
62
|
+
curb.expects(:http_put)
|
63
|
+
curb.expects(:response_code).returns(200)
|
64
|
+
curb.expects(:headers).returns(Hash.new)
|
65
|
+
curb.expects(:body_str).returns(Fixture.xml)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return a valid HTTPI::Response" do
|
69
|
+
request = HTTPI::Request.new :url => "http://example.com"
|
70
|
+
adapter.put(request).should be_a_valid_httpi_response
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#delete" do
|
75
|
+
before do
|
76
|
+
curb.expects(:http_delete)
|
77
|
+
curb.expects(:response_code).returns(200)
|
78
|
+
curb.expects(:headers).returns(Hash.new)
|
79
|
+
curb.expects(:body_str).returns("")
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return a valid HTTPI::Response" do
|
83
|
+
request = HTTPI::Request.new :url => "http://example.com"
|
84
|
+
adapter.delete(request).should be_a_valid_httpi_response
|
85
|
+
end
|
47
86
|
end
|
48
87
|
|
49
88
|
end
|
@@ -6,6 +6,7 @@ require "httpclient"
|
|
6
6
|
|
7
7
|
describe HTTPI::Adapter::HTTPClient do
|
8
8
|
let(:adapter) { HTTPI::Adapter::HTTPClient.new }
|
9
|
+
let(:httpclient) { HTTPClient.any_instance }
|
9
10
|
|
10
11
|
describe ".new" do
|
11
12
|
it "should require the HTTPClient gem" do
|
@@ -38,8 +39,40 @@ describe HTTPI::Adapter::HTTPClient do
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
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
|
+
it "should return a valid HTTPI::Response" do
|
50
|
+
adapter.head(@request).should be_a_valid_httpi_response
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
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)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should return a valid HTTPI::Response" do
|
62
|
+
adapter.put(@request).should be_a_valid_httpi_response
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
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, nil, @request.headers).returns(response)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return a valid HTTPI::Response" do
|
74
|
+
adapter.delete(@request).should be_a_valid_httpi_response
|
75
|
+
end
|
43
76
|
end
|
44
77
|
|
45
78
|
end
|
data/spec/httpi/httpi_spec.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "httpi"
|
3
3
|
|
4
|
+
require "httpclient"
|
5
|
+
require "curb"
|
6
|
+
|
4
7
|
describe HTTPI do
|
5
8
|
let(:client) { HTTPI }
|
6
9
|
let(:default_adapter) { HTTPI::Adapter.find HTTPI::Adapter.use }
|
@@ -41,25 +44,29 @@ describe HTTPI do
|
|
41
44
|
client.get "http://example.com", :curb
|
42
45
|
end
|
43
46
|
end
|
44
|
-
|
45
|
-
|
47
|
+
|
48
|
+
shared_examples_for "a request method" do
|
46
49
|
context "(with a block)" do
|
47
50
|
it "should yield the HTTP client instance used for the request" do
|
48
|
-
client.
|
51
|
+
client.delete "http://example.com" do |http|
|
49
52
|
http.should be_an(HTTPClient)
|
50
53
|
end
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
54
|
-
it "
|
55
|
-
lambda { client.
|
57
|
+
it "and raise an ArgumentError in case of an invalid adapter" do
|
58
|
+
lambda { client.delete HTTPI::Request.new, :invalid }.should raise_error(ArgumentError)
|
56
59
|
end
|
57
60
|
|
58
|
-
it "
|
59
|
-
lambda { client.
|
61
|
+
it "and raise an ArgumentError in case of an invalid URL" do
|
62
|
+
lambda { client.delete "invalid" }.should raise_error(ArgumentError)
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
66
|
+
describe ".get" do
|
67
|
+
it_should_behave_like "a request method"
|
68
|
+
end
|
69
|
+
|
63
70
|
describe ".post(request)" do
|
64
71
|
it "should execute an HTTP POST request using the default adapter" do
|
65
72
|
request = HTTPI::Request.new
|
@@ -99,21 +106,129 @@ describe HTTPI do
|
|
99
106
|
end
|
100
107
|
|
101
108
|
describe ".post" do
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
109
|
+
it_should_behave_like "a request method"
|
110
|
+
end
|
111
|
+
|
112
|
+
describe ".head(request)" do
|
113
|
+
it "should execute an HTTP HEAD request using the default adapter" do
|
114
|
+
request = HTTPI::Request.new
|
115
|
+
default_adapter.any_instance.expects(:head).with(request)
|
116
|
+
|
117
|
+
client.head request
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe ".head(request, adapter)" do
|
122
|
+
it "should execute an HTTP HEAD request using the given adapter" do
|
123
|
+
request = HTTPI::Request.new
|
124
|
+
curb.any_instance.expects(:head).with(request)
|
125
|
+
|
126
|
+
client.head request, :curb
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe ".head(url)" do
|
131
|
+
it "should execute an HTTP HEAD request using the default adapter" do
|
132
|
+
HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
|
133
|
+
default_adapter.any_instance.expects(:head).with(instance_of(HTTPI::Request))
|
134
|
+
|
135
|
+
client.head "http://example.com"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe ".head(url, adapter)" do
|
140
|
+
it "should execute an HTTP HEAD request using the given adapter" do
|
141
|
+
HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
|
142
|
+
curb.any_instance.expects(:head).with(instance_of(HTTPI::Request))
|
143
|
+
|
144
|
+
client.head "http://example.com", :curb
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe ".head" do
|
149
|
+
it_should_behave_like "a request method"
|
150
|
+
end
|
151
|
+
|
152
|
+
describe ".put(request)" do
|
153
|
+
it "should execute an HTTP PUT request using the default adapter" do
|
154
|
+
request = HTTPI::Request.new
|
155
|
+
default_adapter.any_instance.expects(:put).with(request)
|
156
|
+
|
157
|
+
client.put request
|
108
158
|
end
|
159
|
+
end
|
109
160
|
|
110
|
-
|
111
|
-
|
161
|
+
describe ".put(request, adapter)" do
|
162
|
+
it "should execute an HTTP PUT request using the given adapter" do
|
163
|
+
request = HTTPI::Request.new
|
164
|
+
curb.any_instance.expects(:put).with(request)
|
165
|
+
|
166
|
+
client.put request, :curb
|
112
167
|
end
|
168
|
+
end
|
113
169
|
|
114
|
-
|
115
|
-
|
170
|
+
describe ".put(url, body)" do
|
171
|
+
it "should execute an HTTP PUT request using the default adapter" do
|
172
|
+
HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
|
173
|
+
HTTPI::Request.any_instance.expects(:body=).with("<some>xml</some>")
|
174
|
+
default_adapter.any_instance.expects(:put).with(instance_of(HTTPI::Request))
|
175
|
+
|
176
|
+
client.put "http://example.com", "<some>xml</some>"
|
116
177
|
end
|
117
178
|
end
|
118
179
|
|
180
|
+
describe ".put(url, body, adapter)" do
|
181
|
+
it "should execute an HTTP PUT request using the given adapter" do
|
182
|
+
HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
|
183
|
+
HTTPI::Request.any_instance.expects(:body=).with("<some>xml</some>")
|
184
|
+
curb.any_instance.expects(:put).with(instance_of(HTTPI::Request))
|
185
|
+
|
186
|
+
client.put "http://example.com", "<some>xml</some>", :curb
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe ".put" do
|
191
|
+
it_should_behave_like "a request method"
|
192
|
+
end
|
193
|
+
|
194
|
+
describe ".delete(request)" do
|
195
|
+
it "should execute an HTTP DELETE request using the default adapter" do
|
196
|
+
request = HTTPI::Request.new
|
197
|
+
default_adapter.any_instance.expects(:delete).with(request)
|
198
|
+
|
199
|
+
client.delete request
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe ".delete(request, adapter)" do
|
204
|
+
it "should execute an HTTP DELETE request using the given adapter" do
|
205
|
+
request = HTTPI::Request.new
|
206
|
+
curb.any_instance.expects(:delete).with(request)
|
207
|
+
|
208
|
+
client.delete request, :curb
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe ".delete(url)" do
|
213
|
+
it "should execute an HTTP DELETE request using the default adapter" do
|
214
|
+
HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
|
215
|
+
default_adapter.any_instance.expects(:delete).with(instance_of(HTTPI::Request))
|
216
|
+
|
217
|
+
client.delete "http://example.com"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe ".delete(url, adapter)" do
|
222
|
+
it "should execute an HTTP DELETE request using the given adapter" do
|
223
|
+
HTTPI::Request.any_instance.expects(:url=).with("http://example.com")
|
224
|
+
curb.any_instance.expects(:delete).with(instance_of(HTTPI::Request))
|
225
|
+
|
226
|
+
client.delete "http://example.com", :curb
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe ".delete" do
|
231
|
+
it_should_behave_like "a request method"
|
232
|
+
end
|
233
|
+
|
119
234
|
end
|
data/spec/httpi/request_spec.rb
CHANGED
@@ -99,6 +99,65 @@ describe HTTPI::Request do
|
|
99
99
|
request.basic_auth nil
|
100
100
|
request.basic_auth.should be_nil
|
101
101
|
end
|
102
|
-
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#digest_auth" do
|
105
|
+
it "lets you specify the digest auth credentials" do
|
106
|
+
request.digest_auth "username", "password"
|
107
|
+
request.digest_auth.should == ["username", "password"]
|
108
|
+
end
|
109
|
+
|
110
|
+
it "also accepts an Array of credentials" do
|
111
|
+
request.digest_auth ["username", "password"]
|
112
|
+
request.digest_auth.should == ["username", "password"]
|
113
|
+
end
|
114
|
+
|
115
|
+
it "lets you reset the credentials" do
|
116
|
+
request.digest_auth "username", "password"
|
117
|
+
request.digest_auth.should == ["username", "password"]
|
103
118
|
|
119
|
+
request.digest_auth nil
|
120
|
+
request.digest_auth.should be_nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#auth?" do
|
125
|
+
it "should return false unless any authentication credentials were specified" do
|
126
|
+
request.auth?.should be_false
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should return true if HTTP basic auth authentication credentials were specified" do
|
130
|
+
request.basic_auth "username", "password"
|
131
|
+
request.auth?.should be_true
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should return true if HTTP digest auth authentication credentials were specified" do
|
135
|
+
request.digest_auth "username", "password"
|
136
|
+
request.auth?.should be_true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "#credentials" do
|
141
|
+
it "return the credentials for HTTP basic auth" do
|
142
|
+
request.basic_auth "username", "basic"
|
143
|
+
request.credentials.should == ["username", "basic"]
|
144
|
+
end
|
145
|
+
|
146
|
+
it "return the credentials for HTTP digest auth" do
|
147
|
+
request.digest_auth "username", "digest"
|
148
|
+
request.credentials.should == ["username", "digest"]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#auth_type" do
|
153
|
+
it "should return :basic for HTTP basic auth" do
|
154
|
+
request.basic_auth "username", "password"
|
155
|
+
request.auth_type.should == :basic
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should return :digest for HTTP basic auth" do
|
159
|
+
request.digest_auth "username", "password"
|
160
|
+
request.auth_type.should == :digest
|
161
|
+
end
|
162
|
+
end
|
104
163
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "httpi"
|
3
|
+
|
4
|
+
describe HTTPI do
|
5
|
+
let(:client) { HTTPI }
|
6
|
+
|
7
|
+
# Uses example.com for basic request methods and webdav.org
|
8
|
+
# for HTTP basic and digest authentication.
|
9
|
+
#
|
10
|
+
# http://example.com
|
11
|
+
# http://test.webdav.org
|
12
|
+
|
13
|
+
before :all do
|
14
|
+
@username = @password = "user1"
|
15
|
+
@error_message = "Authorization Required"
|
16
|
+
@example_web_page = "Example Web Page"
|
17
|
+
end
|
18
|
+
|
19
|
+
HTTPI::Adapter.adapters.keys.each do |adapter|
|
20
|
+
context "using :#{adapter}" do
|
21
|
+
it "should execute an HTTP GET request" do
|
22
|
+
response = HTTPI.get "http://example.com", adapter
|
23
|
+
response.body.should include(@example_web_page)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should execute an HTTP POST request" do
|
27
|
+
response = HTTPI.post "http://example.com", "<some>xml</some>", adapter
|
28
|
+
response.body.should include(@example_web_page)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should execute an HTTP HEAD request" do
|
32
|
+
response = HTTPI.head "http://example.com", adapter
|
33
|
+
response.code.should == 200
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should execute an HTTP PUT request" do
|
37
|
+
response = HTTPI.put "http://example.com", "<some>xml</some>", adapter
|
38
|
+
response.body.should include("PUT is not allowed")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should execute an HTTP DELETE request" do
|
42
|
+
response = HTTPI.delete "http://example.com", adapter
|
43
|
+
response.body.should include("DELETE is not allowed")
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with HTTP basic authentication" do
|
47
|
+
it "requires a username and password" do
|
48
|
+
request = HTTPI::Request.new :url => "http://test.webdav.org/auth-basic/"
|
49
|
+
request.basic_auth @username, @password
|
50
|
+
|
51
|
+
response = HTTPI.get request, adapter
|
52
|
+
response.body.should_not include(@error_message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with HTTP digest authentication" do
|
57
|
+
it "requires a username and password" do
|
58
|
+
request = HTTPI::Request.new :url => "http://test.webdav.org/auth-digest/"
|
59
|
+
request.digest_auth @username, @password
|
60
|
+
|
61
|
+
response = HTTPI.get request, adapter
|
62
|
+
response.body.should_not include(@error_message)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Daniel Harrington
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-09-
|
19
|
+
date: 2010-09-25 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -96,8 +96,10 @@ extra_rdoc_files: []
|
|
96
96
|
files:
|
97
97
|
- Gemfile
|
98
98
|
- Gemfile.lock
|
99
|
+
- LICENSE
|
99
100
|
- Rakefile
|
100
101
|
- README.md
|
102
|
+
- .autotest
|
101
103
|
- .rspec
|
102
104
|
- autotest/discover.rb
|
103
105
|
- lib/httpi/adapter/curb.rb
|
@@ -115,6 +117,7 @@ files:
|
|
115
117
|
- spec/httpi/httpi_spec.rb
|
116
118
|
- spec/httpi/request_spec.rb
|
117
119
|
- spec/httpi/response_spec.rb
|
120
|
+
- spec/integration/request_spec.rb
|
118
121
|
- spec/spec_helper.rb
|
119
122
|
- spec/support/fixture.rb
|
120
123
|
- spec/support/matchers.rb
|