httpi 0.1.0 → 0.2.0

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