httpi 0.4.1 → 0.5.0

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