httpi 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|