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 ADDED
@@ -0,0 +1,5 @@
1
+ Autotest.add_hook(:initialize) do |at|
2
+ at.clear_mappings
3
+ at.add_mapping(%r%^spec/httpi/.*_spec.rb$%) { |filename, _| filename }
4
+ at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| ["spec/#{m[1]}_spec.rb"] }
5
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- httpi (0.2.0)
4
+ httpi (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
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
- Let's create the most basic request object and execute a GET request:
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
- A POST request with a request object:
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 GET request:
39
+ HTTPI also comes with some shortcuts. This executes a PUT request:
38
40
 
39
- HTTPI.get "http://example.com"
41
+ HTTPI.put "http://example.com", "<some>xml</some>"
40
42
 
41
- And here's a POST:
43
+ And this executes a DELETE request:
42
44
 
43
- HTTPI.post "http://example.com", "<some>xml</some>"
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 currently supports GET and POST requests:
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) # HTTP basic auth credentials
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 and returns an <tt>HTTPI::Response</tt>.
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 and returns an <tt>HTTPI::Response</tt>.
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 = extract_post_args(args)
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
- private
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 extract_post_args(args)
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
@@ -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
- get_request(request) { |client| client.http_get }
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
- post_request(request) { |client, body| client.http_post body }
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 get_request(request)
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 post_request(request)
37
- request.url.query = nil if request.url.query == "wsdl"
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 setup_client(request)
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
- get_request request do |client, url, headers|
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
- post_request request do |client, url, headers, body|
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
- private
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
- def get_request(request)
35
- setup_client request
36
- respond_with yield(client, request.url, request.headers)
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
- def post_request(request)
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
@@ -1,5 +1,5 @@
1
1
  module HTTPI
2
2
 
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
 
5
5
  end
@@ -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
- def curb
46
- Curl::Easy.any_instance
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
- def httpclient
42
- HTTPClient.any_instance
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
@@ -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
- describe ".get" do
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.get "http://example.com" do |http|
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 "should raise an ArgumentError in case of an invalid adapter" do
55
- lambda { client.get HTTPI::Request.new, :invalid }.should raise_error(ArgumentError)
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 "should raise an ArgumentError in case of an invalid URL" do
59
- lambda { client.get "invalid" }.should raise_error(ArgumentError)
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
- context "(with a block)" do
103
- it "should yield the HTTP client instance used for the request" do
104
- client.get "http://example.com", :curb do |http|
105
- http.should be_a(Curl::Easy)
106
- end
107
- end
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
- it "should raise an ArgumentError in case of an invalid adapter" do
111
- lambda { client.post HTTPI::Request.new, :invalid }.should raise_error(ArgumentError)
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
- it "should raise an ArgumentError in case of an invalid URL" do
115
- lambda { client.post "invalid" }.should raise_error(ArgumentError)
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
@@ -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
- end
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: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.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-24 00:00:00 +02:00
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