httpi 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- httpi (0.4.1)
4
+ httpi (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
+ addressable (2.2.1)
10
+ crack (0.1.8)
9
11
  curb (0.7.8)
10
12
  diff-lcs (1.1.2)
11
13
  httpclient (2.1.5.2)
@@ -22,6 +24,9 @@ GEM
22
24
  rspec-mocks (2.0.0.beta.22)
23
25
  rspec-core (= 2.0.0.beta.22)
24
26
  rspec-expectations (= 2.0.0.beta.22)
27
+ webmock (1.3.5)
28
+ addressable (>= 2.1.1)
29
+ crack (>= 0.1.7)
25
30
 
26
31
  PLATFORMS
27
32
  ruby
@@ -32,3 +37,4 @@ DEPENDENCIES
32
37
  httpi!
33
38
  mocha (~> 0.9.8)
34
39
  rspec (= 2.0.0.beta.22)
40
+ webmock (~> 1.3.5)
data/README.md CHANGED
@@ -119,10 +119,11 @@ It currently contains adapters for:
119
119
 
120
120
  * [httpclient](http://rubygems.org/gems/httpclient) ~> 2.1.5
121
121
  * [curb](http://rubygems.org/gems/curb) ~> 0.7.8
122
+ * [net/http](http://ruby-doc.org/stdlib/libdoc/net/http/rdoc)
122
123
 
123
124
  By default, HTTPI uses the `HTTPClient`. But changing the default is fairly easy:
124
125
 
125
- HTTPI::Adapter.use = :curb # or :httpclient
126
+ HTTPI::Adapter.use = :curb # or one of [:httpclient, :net_http]
126
127
 
127
128
  HTTPI::Response
128
129
  ---------------
@@ -134,7 +135,7 @@ It contains the response code, headers and body.
134
135
 
135
136
  response.code # => 200
136
137
  response.headers # => { "Content-Encoding" => "gzip" }
137
- response.body # => "<!DOCTYPE HTML PUBLIC ..."
138
+ response.body # => "<!DOCTYPE HTML PUBLIC ...>"
138
139
 
139
140
  ### TODO
140
141
 
@@ -75,7 +75,7 @@ module HTTPI
75
75
  def get(request, adapter = nil)
76
76
  request = Request.new :url => request if request.kind_of? String
77
77
 
78
- with adapter do |adapter|
78
+ with request, adapter do |adapter|
79
79
  yield adapter.client if block_given?
80
80
  adapter.get request
81
81
  end
@@ -85,7 +85,7 @@ module HTTPI
85
85
  def post(*args)
86
86
  request, adapter = request_and_adapter_from(args)
87
87
 
88
- with adapter do |adapter|
88
+ with request, adapter do |adapter|
89
89
  yield adapter.client if block_given?
90
90
  adapter.post request
91
91
  end
@@ -95,7 +95,7 @@ module HTTPI
95
95
  def head(request, adapter = nil)
96
96
  request = Request.new :url => request if request.kind_of? String
97
97
 
98
- with adapter do |adapter|
98
+ with request, adapter do |adapter|
99
99
  yield adapter.client if block_given?
100
100
  adapter.head request
101
101
  end
@@ -105,7 +105,7 @@ module HTTPI
105
105
  def put(*args)
106
106
  request, adapter = request_and_adapter_from(args)
107
107
 
108
- with adapter do |adapter|
108
+ with request, adapter do |adapter|
109
109
  yield adapter.client if block_given?
110
110
  adapter.put request
111
111
  end
@@ -115,7 +115,7 @@ module HTTPI
115
115
  def delete(request, adapter = nil)
116
116
  request = Request.new :url => request if request.kind_of? String
117
117
 
118
- with adapter do |adapter|
118
+ with request, adapter do |adapter|
119
119
  yield adapter.client if block_given?
120
120
  adapter.delete request
121
121
  end
@@ -131,11 +131,11 @@ module HTTPI
131
131
  [Request.new(:url => args[0], :body => args[1]), args[2]]
132
132
  end
133
133
 
134
- # Accepts an +adapter+ (defaults to <tt>Adapter.use</tt>) and yields a
135
- # new instance of the adapter to a given block.
136
- def with(adapter)
134
+ # Expects a +request+ and an +adapter+ (defaults to <tt>Adapter.use</tt>)
135
+ # and yields a new instance of the adapter to a given block.
136
+ def with(request, adapter)
137
137
  adapter ||= Adapter.use
138
- yield Adapter.find(adapter).new
138
+ yield Adapter.find(adapter).new(request)
139
139
  end
140
140
 
141
141
  end
@@ -1,5 +1,6 @@
1
1
  require "httpi/adapter/httpclient"
2
2
  require "httpi/adapter/curb"
3
+ require "httpi/adapter/net_http"
3
4
 
4
5
  module HTTPI
5
6
 
@@ -27,7 +28,7 @@ module HTTPI
27
28
 
28
29
  # Returns a memoized +Hash+ of adapters.
29
30
  def self.adapters
30
- @adapters ||= { :httpclient => HTTPClient, :curb => Curb }
31
+ @adapters ||= { :httpclient => HTTPClient, :curb => Curb, :net_http => NetHTTP }
31
32
  end
32
33
 
33
34
  # Returns an +adapter+. Raises an +ArgumentError+ unless the +adapter+ exists.
@@ -10,7 +10,7 @@ module HTTPI
10
10
  class Curb
11
11
 
12
12
  # Requires the "curb" gem.
13
- def initialize
13
+ def initialize(request = nil)
14
14
  require "curb"
15
15
  end
16
16
 
@@ -10,7 +10,7 @@ module HTTPI
10
10
  class HTTPClient
11
11
 
12
12
  # Requires the "httpclient" gem.
13
- def initialize
13
+ def initialize(request = nil)
14
14
  require "httpclient"
15
15
  end
16
16
 
@@ -0,0 +1,110 @@
1
+ require "httpi/response"
2
+
3
+ module HTTPI
4
+ module Adapter
5
+
6
+ # = HTTPI::Adapter::NetHTTP
7
+ #
8
+ # Adapter for the Net::HTTP client.
9
+ # http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/
10
+ class NetHTTP
11
+
12
+ # Requires the "net/https" library.
13
+ def initialize(request)
14
+ require "net/https"
15
+ self.client = new_client request
16
+ end
17
+
18
+ attr_reader :client
19
+
20
+ # Executes an HTTP GET request.
21
+ # @see HTTPI.get
22
+ def get(request)
23
+ do_request :get, request do |http, get|
24
+ http.request get
25
+ end
26
+ end
27
+
28
+ # Executes an HTTP POST request.
29
+ # @see HTTPI.post
30
+ def post(request)
31
+ do_request :post, request do |http, post|
32
+ post.body = request.body
33
+ http.request post
34
+ end
35
+ end
36
+
37
+ # Executes an HTTP HEAD request.
38
+ # @see HTTPI.head
39
+ def head(request)
40
+ do_request :head, request do |http, head|
41
+ http.request head
42
+ end
43
+ end
44
+
45
+ # Executes an HTTP PUT request.
46
+ # @see HTTPI.put
47
+ def put(request)
48
+ do_request :put, request do |http, put|
49
+ put.body = request.body
50
+ http.request put
51
+ end
52
+ end
53
+
54
+ # Executes an HTTP DELETE request.
55
+ # @see HTTPI.delete
56
+ def delete(request)
57
+ do_request :delete, request do |http, delete|
58
+ http.request delete
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ attr_writer :client
65
+
66
+ def new_client(request)
67
+ proxy = request.proxy || URI("")
68
+ Net::HTTP::Proxy(proxy.host, proxy.port).new request.url.host, request.url.port
69
+ end
70
+
71
+ def do_request(type, request)
72
+ setup_client request
73
+
74
+ respond_with(client.start do |http|
75
+ yield http, request_client(type, request)
76
+ end)
77
+ end
78
+
79
+ def setup_client(request)
80
+ client.use_ssl = !!(request.url.to_s =~ /^https/)
81
+ client.open_timeout = request.open_timeout
82
+ client.read_timeout = request.read_timeout
83
+ end
84
+
85
+ def request_client(type, request)
86
+ request_class = case type
87
+ when :get then Net::HTTP::Get
88
+ when :post then Net::HTTP::Post
89
+ when :head then Net::HTTP::Head
90
+ when :put then Net::HTTP::Put
91
+ when :delete then Net::HTTP::Delete
92
+ end
93
+
94
+ request_client = request_class.new request.url.request_uri, request.headers
95
+ request_client = auth_setup request_client, request if request.auth?
96
+ request_client
97
+ end
98
+
99
+ def auth_setup(request_client, request)
100
+ request_client.basic_auth *request.credentials if request.auth_type == :basic
101
+ request_client
102
+ end
103
+
104
+ def respond_with(response)
105
+ Response.new response.code, response.to_hash, response.body
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -46,7 +46,7 @@ module HTTPI
46
46
 
47
47
  # Adds a header information to accept gzipped content.
48
48
  def gzip
49
- headers["Accept-encoding"] = "gzip,deflate"
49
+ headers["Accept-Encoding"] = "gzip,deflate"
50
50
  end
51
51
 
52
52
  attr_accessor :body, :open_timeout, :read_timeout, :auth_type
@@ -13,7 +13,7 @@ module HTTPI
13
13
 
14
14
  # Initializer expects an HTTP response +code+, +headers+ and +body+.
15
15
  def initialize(code, headers, body)
16
- self.code = code
16
+ self.code = code.to_i
17
17
  self.headers = headers
18
18
  self.raw_body = body
19
19
  end
@@ -1,5 +1,5 @@
1
1
  module HTTPI
2
2
 
3
- VERSION = "0.4.1"
3
+ VERSION = "0.5.0"
4
4
 
5
5
  end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+ require "httpi/adapter/net_http"
3
+ require "httpi/request"
4
+
5
+ describe HTTPI::Adapter::NetHTTP do
6
+
7
+ def adapter(request)
8
+ @adapter ||= HTTPI::Adapter::NetHTTP.new request
9
+ end
10
+
11
+ describe ".new" do
12
+ it "should require the Net::HTTP library" do
13
+ HTTPI::Adapter::NetHTTP.any_instance.expects(:require).with("net/https")
14
+ HTTPI::Adapter::NetHTTP.new HTTPI::Request.new(:url => "http://example.com")
15
+ end
16
+ end
17
+
18
+ describe "#get" do
19
+ before do
20
+ @request = HTTPI::Request.new :url => "http://example.com"
21
+ stub_request(:get, @request.url.to_s).to_return(:body => Fixture.xml)
22
+ end
23
+
24
+ it "should return a valid HTTPI::Response" do
25
+ adapter(@request).get(@request).should match_response(:body => Fixture.xml)
26
+ end
27
+ end
28
+
29
+ describe "#post" do
30
+ before do
31
+ @request = HTTPI::Request.new :url => "http://example.com", :body => Fixture.xml
32
+ stub_request(:post, @request.url.to_s).with(:body => @request.body).to_return(:body => Fixture.xml)
33
+ end
34
+
35
+ it "should return a valid HTTPI::Response" do
36
+ adapter(@request).post(@request).should match_response(:body => Fixture.xml)
37
+ end
38
+ end
39
+
40
+ describe "#head" do
41
+ before do
42
+ @request = HTTPI::Request.new :url => "http://example.com"
43
+ stub_request(:head, @request.url.to_s).to_return(:body => Fixture.xml)
44
+ end
45
+
46
+ it "should return a valid HTTPI::Response" do
47
+ adapter(@request).head(@request).should match_response(:body => Fixture.xml)
48
+ end
49
+ end
50
+
51
+ describe "#put" do
52
+ before do
53
+ @request = HTTPI::Request.new :url => "http://example.com", :body => Fixture.xml
54
+ stub_request(:put, @request.url.to_s).with(:body => @request.body).to_return(:body => Fixture.xml)
55
+ end
56
+
57
+ it "should return a valid HTTPI::Response" do
58
+ adapter(@request).put(@request).should match_response(:body => Fixture.xml)
59
+ end
60
+ end
61
+
62
+ describe "#delete" do
63
+ before do
64
+ @request = HTTPI::Request.new :url => "http://example.com"
65
+ stub_request(:delete, @request.url.to_s)
66
+ end
67
+
68
+ it "should return a valid HTTPI::Response" do
69
+ adapter(@request).delete(@request).should match_response(:body => "")
70
+ end
71
+ end
72
+
73
+ end
@@ -24,10 +24,11 @@ describe HTTPI::Adapter do
24
24
 
25
25
  describe ".adapters" do
26
26
  it "should return a memoized Hash of adapters" do
27
- adapter.adapters.should have(2).items
27
+ adapter.adapters.should have(3).items
28
28
  adapter.adapters.should include(
29
29
  :httpclient => HTTPI::Adapter::HTTPClient,
30
- :curb => HTTPI::Adapter::Curb
30
+ :curb => HTTPI::Adapter::Curb,
31
+ :net_http => HTTPI::Adapter::NetHTTP
31
32
  )
32
33
  end
33
34
  end
@@ -1,9 +1,6 @@
1
1
  require "spec_helper"
2
2
  require "httpi"
3
3
 
4
- require "httpclient"
5
- require "curb"
6
-
7
4
  describe HTTPI do
8
5
  let(:client) { HTTPI }
9
6
  let(:default_adapter) { HTTPI::Adapter.find HTTPI::Adapter.use }
@@ -61,9 +61,9 @@ describe HTTPI::Request do
61
61
  end
62
62
 
63
63
  describe "#gzip" do
64
- it "should add the proper 'Accept-encoding' header" do
64
+ it "should add the proper 'Accept-Encoding' header" do
65
65
  request.gzip
66
- request.headers["Accept-encoding"].should == "gzip,deflate"
66
+ request.headers["Accept-Encoding"].should == "gzip,deflate"
67
67
  end
68
68
  end
69
69
 
@@ -8,6 +8,11 @@ describe HTTPI::Response do
8
8
  it "should return the HTTP response code" do
9
9
  response.code.should == 200
10
10
  end
11
+
12
+ it "should always return an Integer" do
13
+ response = HTTPI::Response.new "200", {}, ""
14
+ response.code.should == 200
15
+ end
11
16
  end
12
17
 
13
18
  describe "#headers" do
@@ -11,57 +11,72 @@ describe HTTPI do
11
11
  # http://test.webdav.org
12
12
 
13
13
  before :all do
14
+ WebMock.allow_net_connect!
15
+
14
16
  @username = @password = "user1"
15
17
  @error_message = "Authorization Required"
16
18
  @example_web_page = "Example Web Page"
17
19
  end
18
20
 
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
21
+ shared_examples_for "an HTTP client" do
22
+ it "and execute an HTTP GET request" do
23
+ response = HTTPI.get "http://example.com", adapter
24
+ response.body.should include(@example_web_page)
25
+ end
25
26
 
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
27
+ it "and execute an HTTP POST request" do
28
+ response = HTTPI.post "http://example.com", "<some>xml</some>", adapter
29
+ response.body.should include(@example_web_page)
30
+ end
30
31
 
31
- it "should execute an HTTP HEAD request" do
32
- response = HTTPI.head "http://example.com", adapter
33
- response.code.should == 200
34
- end
32
+ it "and execute an HTTP HEAD request" do
33
+ response = HTTPI.head "http://example.com", adapter
34
+ response.code.should == 200
35
+ end
35
36
 
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
37
+ it "and execute an HTTP PUT request" do
38
+ response = HTTPI.put "http://example.com", "<some>xml</some>", adapter
39
+ response.body.should include("PUT is not allowed")
40
+ end
40
41
 
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
42
+ it "and execute an HTTP DELETE request" do
43
+ response = HTTPI.delete "http://example.com", adapter
44
+ response.body.should include("DELETE is not allowed")
45
+ end
46
+ end
47
+
48
+ shared_examples_for "it works with HTTP basic auth" do
49
+ it "and access a secured page" do
50
+ request = HTTPI::Request.new :url => "http://test.webdav.org/auth-basic/"
51
+ request.basic_auth @username, @password
45
52
 
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
53
+ response = HTTPI.get request, adapter
54
+ response.body.should_not include(@error_message)
55
+ end
56
+ end
55
57
 
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
58
+ shared_examples_for "it works with HTTP digest auth" do
59
+ it "requires a username and password" do
60
+ request = HTTPI::Request.new :url => "http://test.webdav.org/auth-digest/"
61
+ request.digest_auth @username, @password
62
+
63
+ response = HTTPI.get request, adapter
64
+ response.body.should_not include(@error_message)
65
+ end
66
+ end
67
+
68
+ HTTPI::Adapter.adapters.keys.each do |adapter|
69
+ context "using :#{adapter}" do
70
+ let(:adapter) { adapter }
71
+ it_should_behave_like "an HTTP client"
72
+ it_should_behave_like "it works with HTTP basic auth"
73
+ end
74
+ end
75
+
76
+ (HTTPI::Adapter.adapters.keys - [:net_http]).each do |adapter|
77
+ context "using :#{adapter}" do
78
+ let(:adapter) { adapter }
79
+ it_should_behave_like "it works with HTTP digest auth"
65
80
  end
66
81
  end
67
82
 
@@ -1,7 +1,9 @@
1
1
  require "rspec"
2
2
  require "mocha"
3
+ require "webmock/rspec"
3
4
 
4
5
  RSpec.configure do |config|
6
+ config.include WebMock
5
7
  config.mock_with :mocha
6
8
  end
7
9
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpi
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 11
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 4
8
- - 1
9
- version: 0.4.1
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Daniel Harrington
@@ -15,16 +16,18 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2010-09-28 00:00:00 +02:00
19
+ date: 2010-10-09 00:00:00 +02:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
23
  name: httpclient
23
24
  prerelease: false
24
25
  requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
25
27
  requirements:
26
28
  - - ~>
27
29
  - !ruby/object:Gem::Version
30
+ hash: 1
28
31
  segments:
29
32
  - 2
30
33
  - 1
@@ -36,9 +39,11 @@ dependencies:
36
39
  name: curb
37
40
  prerelease: false
38
41
  requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
39
43
  requirements:
40
44
  - - ~>
41
45
  - !ruby/object:Gem::Version
46
+ hash: 19
42
47
  segments:
43
48
  - 0
44
49
  - 7
@@ -50,9 +55,11 @@ dependencies:
50
55
  name: rspec
51
56
  prerelease: false
52
57
  requirement: &id003 !ruby/object:Gem::Requirement
58
+ none: false
53
59
  requirements:
54
60
  - - "="
55
61
  - !ruby/object:Gem::Version
62
+ hash: 62196431
56
63
  segments:
57
64
  - 2
58
65
  - 0
@@ -66,9 +73,11 @@ dependencies:
66
73
  name: mocha
67
74
  prerelease: false
68
75
  requirement: &id004 !ruby/object:Gem::Requirement
76
+ none: false
69
77
  requirements:
70
78
  - - ~>
71
79
  - !ruby/object:Gem::Version
80
+ hash: 43
72
81
  segments:
73
82
  - 0
74
83
  - 9
@@ -76,6 +85,22 @@ dependencies:
76
85
  version: 0.9.8
77
86
  type: :development
78
87
  version_requirements: *id004
88
+ - !ruby/object:Gem::Dependency
89
+ name: webmock
90
+ prerelease: false
91
+ requirement: &id005 !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ hash: 17
97
+ segments:
98
+ - 1
99
+ - 3
100
+ - 5
101
+ version: 1.3.5
102
+ type: :development
103
+ version_requirements: *id005
79
104
  description: HTTPI provides a common interface for different HTTP libraries.
80
105
  email: me@rubiii.com
81
106
  executables: []
@@ -95,6 +120,7 @@ files:
95
120
  - autotest/discover.rb
96
121
  - lib/httpi/adapter/curb.rb
97
122
  - lib/httpi/adapter/httpclient.rb
123
+ - lib/httpi/adapter/net_http.rb
98
124
  - lib/httpi/adapter.rb
99
125
  - lib/httpi/request.rb
100
126
  - lib/httpi/response.rb
@@ -104,6 +130,7 @@ files:
104
130
  - spec/fixtures/xml.xml
105
131
  - spec/httpi/adapter/curb_spec.rb
106
132
  - spec/httpi/adapter/httpclient_spec.rb
133
+ - spec/httpi/adapter/net_http_spec.rb
107
134
  - spec/httpi/adapter_spec.rb
108
135
  - spec/httpi/httpi_spec.rb
109
136
  - spec/httpi/request_spec.rb
@@ -122,23 +149,27 @@ rdoc_options: []
122
149
  require_paths:
123
150
  - lib
124
151
  required_ruby_version: !ruby/object:Gem::Requirement
152
+ none: false
125
153
  requirements:
126
154
  - - ">="
127
155
  - !ruby/object:Gem::Version
156
+ hash: 3
128
157
  segments:
129
158
  - 0
130
159
  version: "0"
131
160
  required_rubygems_version: !ruby/object:Gem::Requirement
161
+ none: false
132
162
  requirements:
133
163
  - - ">="
134
164
  - !ruby/object:Gem::Version
165
+ hash: 3
135
166
  segments:
136
167
  - 0
137
168
  version: "0"
138
169
  requirements: []
139
170
 
140
171
  rubyforge_project: httpi
141
- rubygems_version: 1.3.6
172
+ rubygems_version: 1.3.7
142
173
  signing_key:
143
174
  specification_version: 3
144
175
  summary: Interface for Ruby HTTP libraries