cs-httpi 0.9.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +5 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +66 -0
- data/Gemfile +9 -0
- data/LICENSE +20 -0
- data/README.md +229 -0
- data/Rakefile +18 -0
- data/autotest/discover.rb +1 -0
- data/cs-httpi.gemspec +26 -0
- data/lib/cs-httpi.rb +198 -0
- data/lib/cs-httpi/adapter.rb +67 -0
- data/lib/cs-httpi/adapter/curb.rb +119 -0
- data/lib/cs-httpi/adapter/httpclient.rb +98 -0
- data/lib/cs-httpi/adapter/net_http.rb +115 -0
- data/lib/cs-httpi/auth/config.rb +78 -0
- data/lib/cs-httpi/auth/ssl.rb +91 -0
- data/lib/cs-httpi/dime.rb +56 -0
- data/lib/cs-httpi/request.rb +99 -0
- data/lib/cs-httpi/response.rb +85 -0
- data/lib/cs-httpi/version.rb +5 -0
- data/nbproject/private/private.properties +2 -0
- data/nbproject/private/rake-d.txt +0 -0
- data/nbproject/project.properties +7 -0
- data/nbproject/project.xml +15 -0
- data/spec/cs-httpi/adapter/curb_spec.rb +232 -0
- data/spec/cs-httpi/adapter/httpclient_spec.rb +164 -0
- data/spec/cs-httpi/adapter/net_http_spec.rb +142 -0
- data/spec/cs-httpi/adapter_spec.rb +55 -0
- data/spec/cs-httpi/auth/config_spec.rb +117 -0
- data/spec/cs-httpi/auth/ssl_spec.rb +128 -0
- data/spec/cs-httpi/httpi_spec.rb +284 -0
- data/spec/cs-httpi/request_spec.rb +140 -0
- data/spec/cs-httpi/response_spec.rb +125 -0
- data/spec/fixtures/attachment.gif +0 -0
- data/spec/fixtures/client_cert.pem +16 -0
- data/spec/fixtures/client_key.pem +15 -0
- data/spec/fixtures/xml.gz +0 -0
- data/spec/fixtures/xml.xml +10 -0
- data/spec/fixtures/xml_dime.dime +0 -0
- data/spec/fixtures/xml_dime.xml +1 -0
- data/spec/integration/request_spec.rb +95 -0
- data/spec/integration/server.rb +39 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/fixture.rb +27 -0
- data/spec/support/matchers.rb +19 -0
- metadata +158 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
require "cs-httpi/adapter/httpclient"
|
2
|
+
require "cs-httpi/adapter/curb"
|
3
|
+
require "cs-httpi/adapter/net_http"
|
4
|
+
|
5
|
+
module HTTPI
|
6
|
+
|
7
|
+
# = HTTPI::Adapter
|
8
|
+
#
|
9
|
+
# Manages the adapter classes. Currently supports:
|
10
|
+
#
|
11
|
+
# * httpclient
|
12
|
+
# * curb
|
13
|
+
# * net/http
|
14
|
+
module Adapter
|
15
|
+
|
16
|
+
ADAPTERS = {
|
17
|
+
:httpclient => { :class => HTTPClient, :require => "httpclient" },
|
18
|
+
:curb => { :class => Curb, :require => "curb" },
|
19
|
+
:net_http => { :class => NetHTTP, :require => "net/https" }
|
20
|
+
}
|
21
|
+
|
22
|
+
LOAD_ORDER = [:httpclient, :curb, :net_http]
|
23
|
+
|
24
|
+
class << self
|
25
|
+
|
26
|
+
def use=(adapter)
|
27
|
+
return @adapter = nil if adapter.nil?
|
28
|
+
|
29
|
+
validate_adapter! adapter
|
30
|
+
load_adapter adapter
|
31
|
+
@adapter = adapter
|
32
|
+
end
|
33
|
+
|
34
|
+
def use
|
35
|
+
@adapter ||= default_adapter
|
36
|
+
end
|
37
|
+
|
38
|
+
def load(adapter)
|
39
|
+
adapter = adapter ? validate_adapter!(adapter) : use
|
40
|
+
[adapter, ADAPTERS[adapter][:class]]
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def validate_adapter!(adapter)
|
46
|
+
raise ArgumentError, "Invalid HTTPI adapter: #{adapter}" unless ADAPTERS[adapter]
|
47
|
+
adapter
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_adapter
|
51
|
+
LOAD_ORDER.each do |adapter|
|
52
|
+
begin
|
53
|
+
load_adapter adapter
|
54
|
+
return adapter
|
55
|
+
rescue LoadError
|
56
|
+
next
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def load_adapter(adapter)
|
62
|
+
require ADAPTERS[adapter][:require]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require "cs-httpi/response"
|
2
|
+
|
3
|
+
module HTTPI
|
4
|
+
module Adapter
|
5
|
+
|
6
|
+
# = HTTPI::Adapter::Curb
|
7
|
+
#
|
8
|
+
# Adapter for the Curb client.
|
9
|
+
# http://rubygems.org/gems/curb
|
10
|
+
class Curb
|
11
|
+
|
12
|
+
def initialize(request = nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a memoized <tt>Curl::Easy</tt> instance.
|
16
|
+
def client
|
17
|
+
@client ||= Curl::Easy.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Executes an HTTP GET request.
|
21
|
+
# @see HTTPI.get
|
22
|
+
def get(request)
|
23
|
+
do_request(request) { |client| client.http_get }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Executes an HTTP POST request.
|
27
|
+
# @see HTTPI.post
|
28
|
+
def post(request)
|
29
|
+
do_request(request) { |client| client.http_post request.body }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Executes an HTTP HEAD request.
|
33
|
+
# @see HTTPI.head
|
34
|
+
def head(request)
|
35
|
+
do_request(request) { |client| client.http_head }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Executes an HTTP PUT request.
|
39
|
+
# @see HTTPI.put
|
40
|
+
def put(request)
|
41
|
+
do_request(request) { |client| client.http_put request.body }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Executes an HTTP DELETE request.
|
45
|
+
# @see HTTPI.delete
|
46
|
+
def delete(request)
|
47
|
+
do_request(request) { |client| client.http_delete }
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def do_request(request)
|
53
|
+
setup_client request
|
54
|
+
yield client
|
55
|
+
respond_with client
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup_client(request)
|
59
|
+
basic_setup request
|
60
|
+
setup_http_auth request if request.auth.http?
|
61
|
+
setup_ssl_auth request.auth.ssl if request.auth.ssl?
|
62
|
+
end
|
63
|
+
|
64
|
+
def basic_setup(request)
|
65
|
+
client.url = request.url.to_s
|
66
|
+
client.proxy_url = request.proxy.to_s if request.proxy
|
67
|
+
client.timeout = request.read_timeout if request.read_timeout
|
68
|
+
client.connect_timeout = request.open_timeout if request.open_timeout
|
69
|
+
client.headers = request.headers.to_hash
|
70
|
+
client.verbose = false
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup_http_auth(request)
|
74
|
+
client.http_auth_types = request.auth.type
|
75
|
+
client.username, client.password = *request.auth.credentials
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup_ssl_auth(ssl)
|
79
|
+
client.cert_key = ssl.cert_key_file
|
80
|
+
client.cert = ssl.cert_file
|
81
|
+
client.cacert = ssl.ca_cert_file if ssl.ca_cert_file
|
82
|
+
client.certtype = ssl.cert_type.to_s.upcase
|
83
|
+
client.ssl_verify_peer = ssl.verify_mode == :peer
|
84
|
+
end
|
85
|
+
|
86
|
+
def respond_with(client)
|
87
|
+
status, headers = parse_header_string(client.header_str)
|
88
|
+
Response.new client.response_code, headers, client.body_str
|
89
|
+
end
|
90
|
+
|
91
|
+
# Borrowed from Webmock's Curb adapter:
|
92
|
+
# http://github.com/bblimke/webmock/blob/master/lib/webmock/http_lib_adapters/curb.rb
|
93
|
+
def parse_header_string(header_string)
|
94
|
+
status, headers = nil, {}
|
95
|
+
return [status, headers] unless header_string
|
96
|
+
|
97
|
+
header_string.split(/\r\n/).each do |header|
|
98
|
+
if header =~ %r|^HTTP/1.[01] \d\d\d (.*)|
|
99
|
+
status = $1
|
100
|
+
else
|
101
|
+
parts = header.split(':', 2)
|
102
|
+
unless parts.empty?
|
103
|
+
parts[1].strip! unless parts[1].nil?
|
104
|
+
if headers.has_key?(parts[0])
|
105
|
+
headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array
|
106
|
+
headers[parts[0]] << parts[1]
|
107
|
+
else
|
108
|
+
headers[parts[0]] = parts[1]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
[status, headers]
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require "cs-httpi/response"
|
2
|
+
|
3
|
+
module HTTPI
|
4
|
+
module Adapter
|
5
|
+
|
6
|
+
# = HTTPI::Adapter::HTTPClient
|
7
|
+
#
|
8
|
+
# Adapter for the HTTPClient client.
|
9
|
+
# http://rubygems.org/gems/httpclient
|
10
|
+
class HTTPClient
|
11
|
+
|
12
|
+
def initialize(request = nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a memoized <tt>HTTPClient</tt> instance.
|
16
|
+
def client
|
17
|
+
@client ||= ::HTTPClient.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Executes an HTTP GET request.
|
21
|
+
# @see HTTPI.get
|
22
|
+
def get(request)
|
23
|
+
do_request request do |url, headers|
|
24
|
+
client.get url, nil, headers
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Executes an HTTP POST request.
|
29
|
+
# @see HTTPI.post
|
30
|
+
def post(request)
|
31
|
+
do_request request do |url, headers, body|
|
32
|
+
client.post url, body, headers
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Executes an HTTP HEAD request.
|
37
|
+
# @see HTTPI.head
|
38
|
+
def head(request)
|
39
|
+
do_request request do |url, headers|
|
40
|
+
client.head url, nil, headers
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Executes an HTTP PUT request.
|
45
|
+
# @see HTTPI.put
|
46
|
+
def put(request)
|
47
|
+
do_request request do |url, headers, body|
|
48
|
+
client.put url, body, headers
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Executes an HTTP DELETE request.
|
53
|
+
# @see HTTPI.delete
|
54
|
+
def delete(request)
|
55
|
+
do_request request do |url, headers|
|
56
|
+
client.delete url, headers
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def do_request(request)
|
63
|
+
setup_client request
|
64
|
+
respond_with yield(request.url, request.headers, request.body)
|
65
|
+
end
|
66
|
+
|
67
|
+
def setup_client(request)
|
68
|
+
basic_setup request
|
69
|
+
setup_auth request if request.auth.http?
|
70
|
+
setup_ssl_auth request.auth.ssl if request.auth.ssl?
|
71
|
+
end
|
72
|
+
|
73
|
+
def basic_setup(request)
|
74
|
+
client.proxy = request.proxy if request.proxy
|
75
|
+
client.connect_timeout = request.open_timeout if request.open_timeout
|
76
|
+
client.receive_timeout = request.read_timeout if request.read_timeout
|
77
|
+
end
|
78
|
+
|
79
|
+
def setup_auth(request)
|
80
|
+
client.set_auth request.url, *request.auth.credentials
|
81
|
+
end
|
82
|
+
|
83
|
+
def setup_ssl_auth(ssl)
|
84
|
+
unless ssl.verify_mode == :none
|
85
|
+
client.ssl_config.client_cert = ssl.cert
|
86
|
+
client.ssl_config.client_key = ssl.cert_key
|
87
|
+
client.ssl_config.client_ca = ssl.ca_cert if ssl.ca_cert_file
|
88
|
+
end
|
89
|
+
client.ssl_config.verify_mode = ssl.openssl_verify_mode
|
90
|
+
end
|
91
|
+
|
92
|
+
def respond_with(response)
|
93
|
+
Response.new response.code, Hash[*response.header.all.flatten], response.content
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "cs-httpi/response"
|
3
|
+
|
4
|
+
module HTTPI
|
5
|
+
module Adapter
|
6
|
+
|
7
|
+
# = HTTPI::Adapter::NetHTTP
|
8
|
+
#
|
9
|
+
# Adapter for the Net::HTTP client.
|
10
|
+
# http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/
|
11
|
+
class NetHTTP
|
12
|
+
|
13
|
+
def initialize(request)
|
14
|
+
self.client = new_client request
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :client
|
18
|
+
|
19
|
+
# Executes an HTTP GET request.
|
20
|
+
# @see HTTPI.get
|
21
|
+
def get(request)
|
22
|
+
do_request :get, request do |http, get|
|
23
|
+
http.request get
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Executes an HTTP POST request.
|
28
|
+
# @see HTTPI.post
|
29
|
+
def post(request)
|
30
|
+
do_request :post, request do |http, post|
|
31
|
+
post.body = request.body
|
32
|
+
http.request post
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Executes an HTTP HEAD request.
|
37
|
+
# @see HTTPI.head
|
38
|
+
def head(request)
|
39
|
+
do_request :head, request do |http, head|
|
40
|
+
http.request head
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Executes an HTTP PUT request.
|
45
|
+
# @see HTTPI.put
|
46
|
+
def put(request)
|
47
|
+
do_request :put, request do |http, put|
|
48
|
+
put.body = request.body
|
49
|
+
http.request put
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Executes an HTTP DELETE request.
|
54
|
+
# @see HTTPI.delete
|
55
|
+
def delete(request)
|
56
|
+
do_request :delete, request do |http, delete|
|
57
|
+
http.request delete
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
attr_writer :client
|
64
|
+
|
65
|
+
def new_client(request)
|
66
|
+
proxy = request.proxy || URI("")
|
67
|
+
Net::HTTP::Proxy(proxy.host, proxy.port).new request.url.host, request.url.port
|
68
|
+
end
|
69
|
+
|
70
|
+
def do_request(type, request)
|
71
|
+
setup_client request
|
72
|
+
setup_ssl_auth request.auth.ssl if request.auth.ssl?
|
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.ssl?
|
81
|
+
client.open_timeout = request.open_timeout if request.open_timeout
|
82
|
+
client.read_timeout = request.read_timeout if request.read_timeout
|
83
|
+
end
|
84
|
+
|
85
|
+
def setup_ssl_auth(ssl)
|
86
|
+
client.key = ssl.cert_key
|
87
|
+
client.cert = ssl.cert
|
88
|
+
client.ca_file = ssl.ca_cert_file if ssl.ca_cert_file
|
89
|
+
client.verify_mode = ssl.openssl_verify_mode
|
90
|
+
end
|
91
|
+
|
92
|
+
def request_client(type, request)
|
93
|
+
request_class = case type
|
94
|
+
when :get then Net::HTTP::Get
|
95
|
+
when :post then Net::HTTP::Post
|
96
|
+
when :head then Net::HTTP::Head
|
97
|
+
when :put then Net::HTTP::Put
|
98
|
+
when :delete then Net::HTTP::Delete
|
99
|
+
end
|
100
|
+
|
101
|
+
request_client = request_class.new request.url.request_uri, request.headers
|
102
|
+
request_client.basic_auth *request.auth.credentials if request.auth.basic?
|
103
|
+
|
104
|
+
request_client
|
105
|
+
end
|
106
|
+
|
107
|
+
def respond_with(response)
|
108
|
+
headers = response.to_hash
|
109
|
+
headers.each { |key, value| headers[key] = value[0] }
|
110
|
+
Response.new response.code, headers, response.body
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "cs-httpi/auth/ssl"
|
2
|
+
|
3
|
+
module HTTPI
|
4
|
+
module Auth
|
5
|
+
|
6
|
+
# = HTTPI::Auth::Config
|
7
|
+
#
|
8
|
+
# Manages HTTP and SSL auth configuration. Currently supports HTTP basic/digest
|
9
|
+
# and SSL client authentication.
|
10
|
+
class Config
|
11
|
+
|
12
|
+
# Supported authentication types.
|
13
|
+
TYPES = [:basic, :digest, :ssl]
|
14
|
+
|
15
|
+
# Accessor for the HTTP basic auth credentials.
|
16
|
+
def basic(*args)
|
17
|
+
return @basic if args.empty?
|
18
|
+
|
19
|
+
self.type = :basic
|
20
|
+
@basic = args.flatten.compact
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns whether to use HTTP basic auth.
|
24
|
+
def basic?
|
25
|
+
type == :basic
|
26
|
+
end
|
27
|
+
|
28
|
+
# Accessor for the HTTP digest auth credentials.
|
29
|
+
def digest(*args)
|
30
|
+
return @digest if args.empty?
|
31
|
+
|
32
|
+
self.type = :digest
|
33
|
+
@digest = args.flatten.compact
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns whether to use HTTP digest auth.
|
37
|
+
def digest?
|
38
|
+
type == :digest
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns whether to use HTTP basic or dihest auth.
|
42
|
+
def http?
|
43
|
+
type == :basic || type == :digest
|
44
|
+
end
|
45
|
+
|
46
|
+
# Only available with the httpi-ntlm gem.
|
47
|
+
def ntlm(*args)
|
48
|
+
raise "Install the httpi-ntlm gem for experimental NTLM support"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Only available with the httpi-ntlm gem.
|
52
|
+
def ntlm?
|
53
|
+
raise "Install the httpi-ntlm gem for experimental NTLM support"
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the <tt>HTTPI::Auth::SSL</tt> object.
|
57
|
+
def ssl
|
58
|
+
@ssl ||= SSL.new
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns whether to use SSL client auth.
|
62
|
+
def ssl?
|
63
|
+
ssl.present?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Shortcut method for returning the credentials for the authentication specified.
|
67
|
+
# Returns +nil+ unless any authentication credentials were specified.
|
68
|
+
def credentials
|
69
|
+
return unless type
|
70
|
+
send type
|
71
|
+
end
|
72
|
+
|
73
|
+
# Accessor for the authentication type in use.
|
74
|
+
attr_accessor :type
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|