httpi 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -6,6 +6,6 @@ group :development, :test do
6
6
  end
7
7
 
8
8
  group :test do
9
- gem "rspec", "2.0.0.beta.19"
9
+ gem "rspec", "2.0.0.beta.22"
10
10
  gem "mocha", "~> 0.9.8"
11
11
  end
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ curb (0.7.8)
5
+ diff-lcs (1.1.2)
6
+ httpclient (2.1.5.2)
7
+ mocha (0.9.8)
8
+ rake
9
+ rake (0.8.7)
10
+ rspec (2.0.0.beta.22)
11
+ rspec-core (= 2.0.0.beta.22)
12
+ rspec-expectations (= 2.0.0.beta.22)
13
+ rspec-mocks (= 2.0.0.beta.22)
14
+ rspec-core (2.0.0.beta.22)
15
+ rspec-expectations (2.0.0.beta.22)
16
+ diff-lcs (>= 1.1.2)
17
+ rspec-mocks (2.0.0.beta.22)
18
+ rspec-core (= 2.0.0.beta.22)
19
+ rspec-expectations (= 2.0.0.beta.22)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ curb (~> 0.7.8)
26
+ httpclient (~> 2.1.5)
27
+ mocha (~> 0.9.8)
28
+ rspec (= 2.0.0.beta.22)
@@ -1,6 +1,6 @@
1
1
  = HTTPI
2
2
 
3
- HTTPI provides a common interface for different HTTP libraries.
3
+ HTTPI provides a common interface for Ruby HTTP libraries.
4
4
 
5
5
  == Installation
6
6
 
@@ -8,78 +8,107 @@ The gem is available through {Rubygems}[http://rubygems.org/gems/httpi] and can
8
8
 
9
9
  $ gem install httpi
10
10
 
11
- == Supported libraries
11
+ == Basic examples
12
12
 
13
- * {httpclient}[http://rubygems.org/gems/httpclient] ~> 2.1.5
14
- * {curb}[http://rubygems.org/gems/curb] ~> 0.7.8
13
+ Let's create the most basic request object and execute a GET request:
15
14
 
16
- == Getting started
15
+ request = HTTPI::Request.new :url => "http://example.com"
16
+ HTTPI::Client.get request
17
17
 
18
- To get started, simply create a new HTTPI::Client:
18
+ And a POST request with a request object:
19
19
 
20
- client = HTTPI::Client.new :curb
20
+ request = HTTPI::Request.new
21
+ request.url = "http://post.example.com"
22
+ request.body = "send me"
23
+
24
+ HTTPI::Client.post request
21
25
 
22
- Notice that when you're not passing a library to use, HTTPI will default to use the HTTPClient library:
26
+ Or a GET request using HTTP basic auth and the Curb adapter:
23
27
 
24
- HTTPI::Adapter.use # => :httpclient
28
+ request = HTTPI::Request.new
29
+ request.url = "http://auth.example.com"
30
+ request.basic_auth "username", "password"
31
+
32
+ HTTPI::Client.get request, :curb
25
33
 
26
- Changing the default is fairly easy:
34
+ HTTPI also comes with some shortcuts. This executes a GET request:
27
35
 
28
- HTTPI::Adapter.use = :curb
36
+ HTTPI::Client.get "http://example.com"
29
37
 
30
- == Settings
38
+ And here's a POST:
31
39
 
32
- === #headers
40
+ HTTPI::Client.post "http://example.com", "<some>xml</some>"
33
41
 
34
- Accessor for the HTTP request headers:
42
+ == HTTPI::Request
35
43
 
36
- client.headers = { "Accept-Encoding" => "gzip" }
37
- client.headers # => { "Accept-Encoding" => "gzip" }
44
+ The HTTPI::Request serves as a common denominator of options that HTTPI adapters need to support. It represents an HTTP request and lets you customize various settings:
38
45
 
39
- === #proxy
46
+ * [url] the URL to access
47
+ * [proxy] the proxy server to use
48
+ * [headers] a Hash of HTTP headers
49
+ * [body] the HTTP request body
50
+ * [open_timeout] the open timeout (sec)
51
+ * [read_timeout] the read timeout (sec)
40
52
 
41
- Accessor for the proxy server to use:
53
+ It also contains methods for setting up authentication:
42
54
 
43
- client.proxy = "http://proxy.example.com"
44
- client.proxy # => #<URI::HTTP:0x1026240f0 URL:http://proxy.example.com>
55
+ * [basic_auth] HTTP basic auth credentials
45
56
 
46
- === #auth(username, password)
57
+ ==== TODO:
47
58
 
48
- Setting authentication credentials:
59
+ * Add support for HTTP digest authentication
60
+ * Add support for SSL client authentication
49
61
 
50
- client.auth "username", "password"
62
+ == HTTPI::Client
51
63
 
52
- == Request methods
64
+ The HTTPI::Client uses one of the available adapters to execute HTTP requests. It currently supports GET and POST requests:
53
65
 
54
- === #get(url)
66
+ === GET
55
67
 
56
- Sending an HTTP GET request:
68
+ * get(request, adapter = nil)
69
+ * get(url, adapter = nil)
57
70
 
58
- client.get "http://example.com"
71
+ === POST
59
72
 
60
- === #post(url, body)
73
+ * post(request, adapter = nil)
74
+ * post(url, body, adapter = nil)
61
75
 
62
- Sending an HTTP POST request:
76
+ You can specify the adapter to use per request. Request methods always returns an HTTPI::Response.
63
77
 
64
- client.post "http://example.com", "<some>xml</xml>"
78
+ ==== TODO:
79
+
80
+ * Add support for HEAD, PUT and DELETE requests
81
+
82
+ == HTTPI::Adapter
83
+
84
+ HTTPI uses adapters to support multiple HTTP libraries. It currently contains adapters for:
85
+
86
+ * {httpclient}[http://rubygems.org/gems/httpclient] ~> 2.1.5
87
+ * {curb}[http://rubygems.org/gems/curb] ~> 0.7.8
88
+
89
+ By default, HTTPI uses the HTTPClient. But changing the default is fairly easy:
90
+
91
+ HTTPI::Adapter.use = :curb
92
+
93
+ You can find a list of supported adapters via:
94
+
95
+ HTTPI::Adapter.adapters # returns a Hash of supported adapters
65
96
 
66
97
  == HTTPI::Response
67
98
 
68
- Every HTTP request method is supposed to return an HTTPI::Response containing the response code, headers and body.
99
+ As mentioned before, every request method return an HTTPI::Response. It contains the response code, headers and body.
69
100
 
70
- response = client.get "http://example.com"
101
+ response = HTTPI::Client.get request
71
102
 
72
103
  response.code # => 200
73
104
  response.headers # => { "Content-Encoding" => "gzip" }
74
105
  response.body # => "<!DOCTYPE HTML PUBLIC ..."
75
106
 
76
- == Participate
77
-
78
- I would appreciate any help to support additional libraries and methods!
107
+ ==== TODO
79
108
 
80
- == TODO
109
+ * Return the original HTTPI::Request for debugging purposes
110
+ * Return the time it took to execute the request
81
111
 
82
- Implement methods for:
112
+ == Participate
83
113
 
84
- * add SSL configuration method
85
- * add timeout methods
114
+ We appreciate any help and feedback, so please get in touch!
data/Rakefile CHANGED
@@ -1,8 +1,34 @@
1
+ require "rake"
2
+
1
3
  begin
2
- require "rspec/core/rake_task"
4
+ require "yard"
5
+
6
+ YARD::Rake::YardocTask.new do |t|
7
+ t.files = ["README.rdoc", "lib/**/*.rb"]
8
+ end
9
+ rescue LoadError
10
+ desc message = %{"gem install yard" to generate documentation}
11
+ task("yard") { abort message }
12
+ end
13
+
14
+ begin
15
+ require "metric_fu"
16
+
17
+ MetricFu::Configuration.run do |c|
18
+ c.metrics = [:churn, :flog, :flay, :reek, :roodi, :saikuro] # :rcov seems to be broken
19
+ c.graphs = [:flog, :flay, :reek, :roodi]
20
+ c.rcov[:rcov_opts] << "-Ilib -Ispec"
21
+ end
22
+ rescue LoadError
23
+ desc message = %{"gem install metric_fu" to generate metrics}
24
+ task("metrics:all") { abort message }
25
+ end
3
26
 
27
+ begin
28
+ require "rspec/core/rake_task"
29
+
4
30
  RSpec::Core::RakeTask.new do |t|
5
- t.spec_opts = %w(-fd -c)
31
+ t.rspec_opts = %w(-fd -c)
6
32
  end
7
33
  rescue LoadError
8
34
  task :spec do
@@ -4,7 +4,7 @@ require "httpi/adapter/curb"
4
4
  module HTTPI
5
5
  module Adapter
6
6
 
7
- # The default adapter.
7
+ # The def self.ault adapter.
8
8
  DEFAULT = :httpclient
9
9
 
10
10
  # Returns the adapter to use. Defaults to <tt>HTTPI::Adapter::DEFAULT</tt>.
@@ -1,56 +1,48 @@
1
1
  require "httpi/response"
2
- require "httpi/adapter/base"
3
2
 
4
3
  module HTTPI
5
4
  module Adapter
6
- module Curb
7
- include Base
5
+ class Curb
8
6
 
9
- def setup
7
+ def initialize
10
8
  require "curb"
11
9
  end
12
10
 
13
- def client
14
- @client ||= Curl::Easy.new
11
+ def get(request)
12
+ get_request(request) { |client| client.http_get }
15
13
  end
16
14
 
17
- def headers
18
- client.headers
15
+ def post(request)
16
+ post_request(request) { |client, body| client.http_post body }
19
17
  end
20
18
 
21
- def headers=(headers)
22
- client.headers = headers
23
- end
24
-
25
- def proxy
26
- proxy = client.proxy_url
27
- proxy.kind_of?(URI) ? proxy : URI(proxy)
28
- end
29
-
30
- def proxy=(proxy)
31
- client.proxy_url = proxy
32
- end
19
+ private
33
20
 
34
- def auth(username, password)
35
- client.username = username
36
- client.password = password
21
+ def get_request(request)
22
+ client = client_for request
23
+ yield client
24
+ respond_with client
37
25
  end
38
26
 
39
- def get(url)
40
- client.url = url.to_s
41
- client.http_get
42
- respond
27
+ def post_request(request)
28
+ request.url = request.url.to_s
29
+ request.url.gsub!('?wsdl', '') if request.url =~ /\?wsdl$/
30
+
31
+ client = client_for request
32
+ yield client, request.body
33
+ respond_with client
43
34
  end
44
35
 
45
- def post(url, body)
46
- client.url = url.to_s
47
- client.http_post body
48
- respond
36
+ def client_for(request)
37
+ client = Curl::Easy.new request.url.to_s
38
+ client.timeout = request.read_timeout
39
+ client.connect_timeout = request.open_timeout
40
+ client.headers = request.headers
41
+ client.verbose = false
42
+ client
49
43
  end
50
44
 
51
- private
52
-
53
- def respond
45
+ def respond_with(client)
54
46
  Response.new client.response_code, client.headers, client.body_str
55
47
  end
56
48
 
@@ -1,47 +1,45 @@
1
1
  require "httpi/response"
2
- require "httpi/adapter/base"
3
2
 
4
3
  module HTTPI
5
4
  module Adapter
6
- module HTTPClient
7
- include Base
5
+ class HTTPClient
8
6
 
9
- def setup
7
+ def initialize
10
8
  require "httpclient"
11
9
  end
12
10
 
13
- def client
14
- @client ||= ::HTTPClient.new
11
+ def get(request)
12
+ get_request request do |client, url, headers|
13
+ client.get url, nil, headers
14
+ end
15
15
  end
16
16
 
17
- def headers
18
- @headers ||= {}
17
+ def post(request)
18
+ post_request request do |client, url, headers, body|
19
+ client.post url, body, headers
20
+ end
19
21
  end
20
22
 
21
- attr_writer :headers
22
-
23
- def proxy
24
- client.proxy
25
- end
26
-
27
- def proxy=(proxy)
28
- client.proxy = proxy
29
- end
23
+ private
30
24
 
31
- def auth(username, password)
32
- client.set_auth nil, username, password
25
+ def get_request(request)
26
+ client = client_for request
27
+ respond_with yield(client, request.url, request.headers)
33
28
  end
34
29
 
35
- def get(url)
36
- respond_with client.get(url)
30
+ def post_request(request)
31
+ client = client_for request
32
+ respond_with yield(client, request.url, request.headers, request.body)
37
33
  end
38
34
 
39
- def post(url, body)
40
- respond_with client.post(url, body, headers)
35
+ def client_for(request)
36
+ client = ::HTTPClient.new
37
+ client.proxy = request.proxy if request.proxy
38
+ client.connect_timeout = request.open_timeout
39
+ client.receive_timeout = request.read_timeout
40
+ client
41
41
  end
42
42
 
43
- private
44
-
45
43
  def respond_with(response)
46
44
  Response.new response.code, Hash[response.header.all], response.content
47
45
  end
@@ -1,12 +1,70 @@
1
- require "httpi/interface"
1
+ require "httpi/request"
2
+ require "httpi/adapter"
2
3
 
3
4
  module HTTPI
4
5
  class Client
5
- include Interface
6
+ class << self
6
7
 
7
- def initialize(adapter = nil)
8
- load! adapter
9
- end
8
+ # Executes an HTTP GET request and returns an <tt>HTTPI::Response</tt>.
9
+ #
10
+ # ==== Example
11
+ #
12
+ # Accepts an <tt>HTTPI::Request</tt> and an optional adapter:
13
+ #
14
+ # request = HTTPI::Request.new :url => "http://example.com"
15
+ # HTTPI::Client.get request, :httpclient
16
+ #
17
+ # ==== Shortcut
18
+ #
19
+ # You can also just pass a URL and an optional adapter if you don't
20
+ # need to configure the request:
21
+ #
22
+ # HTTPI::Client.get "http://example.com", :curb
23
+ def get(request, adapter = nil)
24
+ request = Request.new :url => request if request.kind_of? String
25
+ find_adapter(adapter).get request
26
+ end
27
+
28
+ # Executes an HTTP POST request and returns an <tt>HTTPI::Response</tt>.
29
+ #
30
+ # ==== Example
31
+ #
32
+ # Accepts an <tt>HTTPI::Request</tt> and an optional adapter:
33
+ #
34
+ # request = HTTPI::Request.new
35
+ # request.url = "http://example.com"
36
+ # request.body = "<some>xml</some>"
37
+ #
38
+ # HTTPI::Client.post request, :httpclient
39
+ #
40
+ # ==== Shortcut
41
+ #
42
+ # You can also just pass a URL, a request body and an optional adapter
43
+ # if you don't need to configure the request:
44
+ #
45
+ # HTTPI::Client.post "http://example.com", "<some>xml</some>", :curb
46
+ def post(*args)
47
+ request, adapter = extract_post_args(args)
48
+ find_adapter(adapter).post request
49
+ end
50
+
51
+ private
10
52
 
53
+ # Checks whether +args+ contains of an <tt>HTTPI::Request</tt> or a URL
54
+ # and a request body plus an optional adapter and returns an Array with
55
+ # an <tt>HTTPI::Request</tt> and (if given) an adapter.
56
+ def extract_post_args(args)
57
+ return args if args.first.kind_of? Request
58
+ [Request.new(:url => args[0], :body => args[1]), args[2]]
59
+ end
60
+
61
+ # Accepts an +adapter+ (defaults to <tt>Adapter.use</tt>) and returns
62
+ # a new instance of the adapter to use.
63
+ def find_adapter(adapter)
64
+ adapter ||= Adapter.use
65
+ Adapter.find(adapter).new
66
+ end
67
+
68
+ end
11
69
  end
12
70
  end