simple_http 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -0
- data/.gitignore +17 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +5 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +11 -0
- data/certs/tiabas_public.pem +21 -0
- data/lib/simple_http.rb +2 -0
- data/lib/simple_http/connection.rb +187 -0
- data/lib/simple_http/version.rb +18 -0
- data/simple_http.gemspec +26 -0
- data/spec/connection_spec.rb +271 -0
- data/spec/spec_helper.rb +35 -0
- metadata +155 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
b��A��Е�c�|vE\."]���8����M����|o���a�<2���~WV `���tR�l<_���7��[4�'�[����B�R�["��Aώ��S���o�ȵS�����I������3ѫ^X(;���i��Xۦ2�[q�#�#�>p6�k涡��oN�{�`�Hx}G��7�>l�����}pJ� ��F��S`^2������s�X�����/ch��YO���� ��ZSPuZ$����#�+]�/��m�#6QS
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Kevin Mutyaba
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# SimpleHttp
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'simple_http'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install simple_http
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAh0aWFi
|
3
|
+
YXNuazEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
4
|
+
MB4XDTEzMDMwMzA2MjAxNVoXDTE0MDMwMzA2MjAxNVowPzERMA8GA1UEAwwIdGlh
|
5
|
+
YmFzbmsxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
6
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMsmVsErcNuwQLKLh9T6
|
7
|
+
a57QiK35g9zjpID2pUBn4alMTmIeAXg2bXWLdAzU0swcjmaGBWz5AaZeqTnnBveO
|
8
|
+
ZDoH6e811uuRjJMYCkLQxhlghEB0TQkAqOnxlj80TN2jFw+YFWLmSnxR4PBonvpp
|
9
|
+
YwWAY0ylqM54FPRhaAIYC5/3Pvx1SYL9/Us0376HEpV0Rty6VXz7tUzv8vFki5ot
|
10
|
+
gyfp5ceWiYIZjQ9Uvhm4luJSfXci13UHZ0AeO7E1padWlx3z8hZIvjawueTGRe5p
|
11
|
+
BgZlI0+xV2ogvAlu8/NCy0hWUwcpnvRdPyBVDRMli8gXGE9jNv8dBWe67vdjzGSk
|
12
|
+
YDUCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFInh
|
13
|
+
qvJkuISNqDOcsrBRotZC0qolMB0GA1UdEQQWMBSBEnRpYWJhc25rQGdtYWlsLmNv
|
14
|
+
bTAdBgNVHRIEFjAUgRJ0aWFiYXNua0BnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
15
|
+
ggEBAEGb4gRDulJ9jkf5oRLydfw9UZi6fVWj6aaiJfbbT5NLotpVaWnWdCOO7hy8
|
16
|
+
HDPYWN430zLwr0ODOU9XNueKnEkhnBRiYkcQ0JmYddPkL57kp0qlH4g2IqQfQV2W
|
17
|
+
1b7sE410zFHn55B5nihQY3c0MMSL7wq9Dz2EktbIMikf6sG6zfUgYFE4IQGi2RbO
|
18
|
+
xa5fnTWt7KB5DD02HnHLTZ9Hl2kxlPyWwyjREwNwEjPoSUJFEBiosvAml8frUDA9
|
19
|
+
j6fATg/4fqpgILPVqFIGZOMJDFcJy/oehwwxLu5XMx88WFD9jT1vRj77D7iPLbXd
|
20
|
+
rfGs/qCJKgifXd/1am5hlAH5jXU=
|
21
|
+
-----END CERTIFICATE-----
|
data/lib/simple_http.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'addressable/uri'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'net/https'
|
6
|
+
rescue LoadError
|
7
|
+
warn "Warning: no such file to load -- net/https. Make sure openssl is installed if you want ssl support"
|
8
|
+
require 'net/http'
|
9
|
+
end
|
10
|
+
|
11
|
+
module SimpleHttp
|
12
|
+
class Connection
|
13
|
+
|
14
|
+
class UnhandledHTTPMethodError < StandardError; end
|
15
|
+
class UnsupportedSchemeError < StandardError; end
|
16
|
+
|
17
|
+
NET_HTTP_EXCEPTIONS = [
|
18
|
+
EOFError,
|
19
|
+
Errno::ECONNABORTED,
|
20
|
+
Errno::ECONNREFUSED,
|
21
|
+
Errno::ECONNRESET,
|
22
|
+
Errno::EINVAL,
|
23
|
+
Net::HTTPBadResponse,
|
24
|
+
Net::HTTPHeaderSyntaxError,
|
25
|
+
Net::ProtocolError,
|
26
|
+
SocketError,
|
27
|
+
Zlib::GzipFile::Error,
|
28
|
+
]
|
29
|
+
|
30
|
+
attr_accessor :config, :scheme, :host, :port, :max_redirects, :ssl,
|
31
|
+
:user_agent, :accept, :max_redirects, :headers, :uri
|
32
|
+
|
33
|
+
def self.default_options
|
34
|
+
{
|
35
|
+
:headers => {
|
36
|
+
'Accept' => 'application/json',
|
37
|
+
'User-Agent' => "Simple HTTP gem #{SimpleHttp::Version}",
|
38
|
+
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'
|
39
|
+
|
40
|
+
},
|
41
|
+
:ssl => {:verify => true},
|
42
|
+
:max_redirects => 5
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(url, options={})
|
47
|
+
@uri = Addressable::URI.parse(url)
|
48
|
+
self.class.default_options.keys.each do |key|
|
49
|
+
instance_variable_set(:"@#{key}", options.fetch(key, self.class.default_options[key]))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_headers
|
54
|
+
self.class.default_options[:headers]
|
55
|
+
end
|
56
|
+
|
57
|
+
def scheme=(scheme)
|
58
|
+
unless ['http', 'https'].include? scheme
|
59
|
+
raise UnsupportedSchemeError.new "#{scheme} is not supported, only http and https"
|
60
|
+
end
|
61
|
+
@scheme = scheme
|
62
|
+
end
|
63
|
+
|
64
|
+
def scheme
|
65
|
+
@scheme ||= @uri.scheme
|
66
|
+
end
|
67
|
+
|
68
|
+
def host
|
69
|
+
@host ||= @uri.host
|
70
|
+
end
|
71
|
+
|
72
|
+
def port
|
73
|
+
_port = ssl? ? 443 : 80
|
74
|
+
@port = @uri.port || _port
|
75
|
+
end
|
76
|
+
|
77
|
+
def absolute_url(path='')
|
78
|
+
"#{scheme}://#{host}#{path}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def ssl?
|
82
|
+
scheme == "https" ? true : false
|
83
|
+
end
|
84
|
+
|
85
|
+
def ssl=(opts)
|
86
|
+
raise "Expected Hash but got #{opts.class.name}" unless opts.is_a?(Hash)
|
87
|
+
@ssl.merge!(opts)
|
88
|
+
end
|
89
|
+
|
90
|
+
def http_connection(opts={})
|
91
|
+
_host = opts[:host] || host
|
92
|
+
_port = opts[:port] || port
|
93
|
+
_scheme = opts[:scheme] || scheme
|
94
|
+
|
95
|
+
@http_client = Net::HTTP.new(_host, _port)
|
96
|
+
|
97
|
+
configure_ssl(@http_client) if _scheme == 'https'
|
98
|
+
|
99
|
+
@http_client
|
100
|
+
end
|
101
|
+
|
102
|
+
def send_request(method, path, opts={})
|
103
|
+
headers = @headers.merge(opts.fetch(:headers, {}))
|
104
|
+
params = opts[:params] || {}
|
105
|
+
query = Addressable::URI.form_encode(params)
|
106
|
+
method = method.to_sym
|
107
|
+
normalized_path = query.empty? ? path : [path, query].join("?")
|
108
|
+
client = http_connection(opts.fetch(:connection_options, {}))
|
109
|
+
|
110
|
+
if (method == :post || method == :put)
|
111
|
+
headers['Content-Type'] ||= 'application/x-www-form-urlencoded'
|
112
|
+
end
|
113
|
+
|
114
|
+
case method
|
115
|
+
when :get, :delete
|
116
|
+
response = client.send(method, normalized_path, headers)
|
117
|
+
when :post, :put
|
118
|
+
response = client.send(method, path, query, headers)
|
119
|
+
else
|
120
|
+
raise UnhandledHTTPMethodError.new("Unsupported HTTP method, #{method}")
|
121
|
+
end
|
122
|
+
|
123
|
+
status = response.code.to_i
|
124
|
+
|
125
|
+
case status
|
126
|
+
when 301, 302, 303, 307
|
127
|
+
unless redirect_limit_reached?
|
128
|
+
if status == 303
|
129
|
+
method = :get
|
130
|
+
params = nil
|
131
|
+
headers.delete('Content-Type')
|
132
|
+
end
|
133
|
+
redirect_uri = Addressable::URI.parse(response.header['Location'])
|
134
|
+
conn = {
|
135
|
+
:scheme => redirect_uri.scheme,
|
136
|
+
:host => redirect_uri.host,
|
137
|
+
:port => redirect_uri.port
|
138
|
+
}
|
139
|
+
return send_request(method, redirect_uri.path, :params => params, :headers => headers, :connection_options => conn)
|
140
|
+
end
|
141
|
+
when 100..599
|
142
|
+
@redirect_count = 0
|
143
|
+
else
|
144
|
+
raise "Unhandled status code value of #{response.code}"
|
145
|
+
end
|
146
|
+
response
|
147
|
+
rescue *NET_HTTP_EXCEPTIONS
|
148
|
+
raise "Error::ConnectionFailed, #{$!}"
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def configure_ssl(http)
|
154
|
+
http.use_ssl = true
|
155
|
+
http.verify_mode = ssl_verify_mode
|
156
|
+
http.cert_store = ssl_cert_store
|
157
|
+
|
158
|
+
http.cert = ssl[:client_cert] if ssl[:client_cert]
|
159
|
+
http.key = ssl[:client_key] if ssl[:client_key]
|
160
|
+
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
|
161
|
+
http.ca_path = ssl[:ca_path] if ssl[:ca_path]
|
162
|
+
http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
|
163
|
+
http.ssl_version = ssl[:version] if ssl[:version]
|
164
|
+
end
|
165
|
+
|
166
|
+
def ssl_verify_mode
|
167
|
+
if ssl.fetch(:verify, true)
|
168
|
+
OpenSSL::SSL::VERIFY_PEER
|
169
|
+
else
|
170
|
+
OpenSSL::SSL::VERIFY_NONE
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def ssl_cert_store
|
175
|
+
return ssl[:cert_store] if ssl[:cert_store]
|
176
|
+
cert_store = OpenSSL::X509::Store.new
|
177
|
+
cert_store.set_default_paths
|
178
|
+
cert_store
|
179
|
+
end
|
180
|
+
|
181
|
+
def redirect_limit_reached?
|
182
|
+
@redirect_count ||= 0
|
183
|
+
@redirect_count += 1
|
184
|
+
@redirect_count > @max_redirects
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SimpleHttp
|
2
|
+
class Version
|
3
|
+
MAJOR = 0 unless defined? Yammer::MAJOR
|
4
|
+
MINOR = 1 unless defined? Yammer::MINOR
|
5
|
+
PATCH = 1 unless defined? Yammer::PATCH
|
6
|
+
PRE = nil unless defined? Yammer::PRE
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# @return [String]
|
11
|
+
def to_s
|
12
|
+
[MAJOR, MINOR, PATCH, PRE].compact.join('.')
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/simple_http.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/simple_http/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Kevin Mutyaba"]
|
6
|
+
gem.email = ["tiabasnk@gmail.com"]
|
7
|
+
gem.description = %q{A Net::HTTP wrapper}
|
8
|
+
gem.summary = %q{Simple HTTP wrapper for Ruby}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "simple_http"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = SimpleHttp::Version
|
17
|
+
gem.licenses = ['MIT']
|
18
|
+
|
19
|
+
gem.add_development_dependency 'rake'
|
20
|
+
gem.add_development_dependency 'rspec'
|
21
|
+
gem.add_development_dependency 'simplecov', '~> 0.7.1'
|
22
|
+
gem.add_development_dependency 'webmock', '~> 1.9.0'
|
23
|
+
|
24
|
+
gem.cert_chain = ['certs/tiabas_public.pem']
|
25
|
+
gem.signing_key = File.expand_path("~/.gem/certs/private_key.pem") if $0 =~ /gem\z/
|
26
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe SimpleHttp::Connection do
|
4
|
+
|
5
|
+
subject do
|
6
|
+
@conn = SimpleHttp::Connection.new('https://example.com')
|
7
|
+
end
|
8
|
+
|
9
|
+
context "with user options" do
|
10
|
+
before do
|
11
|
+
@options = {
|
12
|
+
:headers => {
|
13
|
+
'Accept' => 'application/json',
|
14
|
+
'User-Agent' => "Simple HTTP gem #{SimpleHttp::Version}",
|
15
|
+
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'
|
16
|
+
},
|
17
|
+
:ssl => {:verify => false},
|
18
|
+
:max_redirects => 2
|
19
|
+
}
|
20
|
+
@conn = SimpleHttp::Connection.new('https://microsoft.com', @options)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "overrides default options" do
|
24
|
+
opts = SimpleHttp::Connection.default_options
|
25
|
+
opts.keys.each do |key|
|
26
|
+
expect(@conn.instance_variable_get(:"@#{key}")).to eq @options[key]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#default_headers" do
|
32
|
+
it "returns user_agent and response format" do
|
33
|
+
expect(subject.default_headers).to eq ({
|
34
|
+
"Accept" => "application/json",
|
35
|
+
"User-Agent" => "Simple HTTP gem #{SimpleHttp::Version}",
|
36
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'
|
37
|
+
})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#scheme" do
|
42
|
+
it "returns the http scheme" do
|
43
|
+
expect(subject.scheme).to eq 'https'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#scheme" do
|
48
|
+
context "scheme is unsupported" do
|
49
|
+
it "raises an error" do
|
50
|
+
expect { subject.scheme = 'ftp'}.to raise_error(SimpleHttp::Connection::UnsupportedSchemeError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "scheme is http" do
|
55
|
+
it "sets the scheme" do
|
56
|
+
subject.scheme = 'http'
|
57
|
+
expect(subject.scheme).to eq 'http'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "scheme is https" do
|
62
|
+
it "sets the scheme" do
|
63
|
+
subject.scheme = 'https'
|
64
|
+
expect(subject.scheme).to eq 'https'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#host" do
|
70
|
+
it "returns the host server" do
|
71
|
+
expect(subject.host).to eq 'example.com'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#port" do
|
76
|
+
it "returns the port" do
|
77
|
+
expect(subject.port).to eq 443
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#ssl?" do
|
82
|
+
context "scheme is https" do
|
83
|
+
it "returns true" do
|
84
|
+
subject.scheme = 'https'
|
85
|
+
expect(subject.ssl?).to eq true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "scheme is http" do
|
90
|
+
it "returns false" do
|
91
|
+
subject.scheme = 'http'
|
92
|
+
expect(subject.ssl?).to eq false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#http_connection" do
|
98
|
+
it "behaves like HTTP client" do
|
99
|
+
expect(subject.http_connection).to respond_to(:get)
|
100
|
+
expect(subject.http_connection).to respond_to(:post)
|
101
|
+
expect(subject.http_connection).to respond_to(:put)
|
102
|
+
expect(subject.http_connection).to respond_to(:delete)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#absolute_url" do
|
107
|
+
context "with no parameters" do
|
108
|
+
it "returns a uri without path" do
|
109
|
+
expect(subject.absolute_url).to eq "https://example.com"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "with parameters" do
|
114
|
+
it "returns a uri with path" do
|
115
|
+
expect(subject.absolute_url('/oauth/v2/authorize')).to eq "https://example.com/oauth/v2/authorize"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#configure_ssl" do
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#redirect_limit_reached?" do
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#ssl_verify_mode" do
|
127
|
+
context "ssl verify set to true" do
|
128
|
+
it "returns OpenSSL::SSL::VERIFY_PEER" do
|
129
|
+
subject.ssl = { :verify => true }
|
130
|
+
expect(subject.send(:ssl_verify_mode)).to eq OpenSSL::SSL::VERIFY_PEER
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "ssl verify set to false" do
|
135
|
+
it "returns OpenSSL::SSL::VERIFY_NONE" do
|
136
|
+
subject.ssl = { :verify => false }
|
137
|
+
expect(subject.send(:ssl_verify_mode)).to eq OpenSSL::SSL::VERIFY_NONE
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "ssl_cert_store" do
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#send_request" do
|
146
|
+
before do
|
147
|
+
@http_ok = OpenStruct.new(
|
148
|
+
:code => '200',
|
149
|
+
:body => 'success',
|
150
|
+
:headers => {'Content-Type' => "application/json"}
|
151
|
+
)
|
152
|
+
@http_redirect = OpenStruct.new(
|
153
|
+
:code => '301',
|
154
|
+
:body => 'redirect',
|
155
|
+
:headers => {'Location' => "https://example.com/members"}
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
context "when method is not supported" do
|
160
|
+
it "raises an error" do
|
161
|
+
expect {subject.send_request(:patch, '/')}.to raise_error(SimpleHttp::Connection::UnhandledHTTPMethodError)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when method is get" do
|
166
|
+
it "returns an http response" do
|
167
|
+
stub_get('/oauth/authorize').with(
|
168
|
+
:query => {:client_id => '001337', :client_secret => 'abcxyz'},
|
169
|
+
:headers => subject.default_headers
|
170
|
+
)
|
171
|
+
subject.send_request(:get, '/oauth/authorize', :params => {:client_id => '001337', :client_secret => 'abcxyz'})
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "when method is delete" do
|
176
|
+
it "returns an http response" do
|
177
|
+
stub_delete('/users/1').with(
|
178
|
+
:headers => subject.default_headers
|
179
|
+
)
|
180
|
+
subject.send_request(:delete, '/users/1')
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "when method is post" do
|
185
|
+
it "returns an http response" do
|
186
|
+
stub_post('/users').with(
|
187
|
+
:body => {:first_name => 'john', :last_name => 'smith'},
|
188
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
189
|
+
)
|
190
|
+
subject.send_request(:post, '/users', :params => {:first_name => 'john', :last_name => 'smith'})
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "when method is put" do
|
195
|
+
it "returns an http response" do
|
196
|
+
stub_put('/users/1').with(
|
197
|
+
:body => {:first_name => 'jane', :last_name => 'doe'},
|
198
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
199
|
+
)
|
200
|
+
subject.send_request(:put, '/users/1', :params => {:first_name => 'jane', :last_name => 'doe'})
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
it "follows redirect" do
|
205
|
+
|
206
|
+
stub_post('/users').with(
|
207
|
+
:body => {:first_name => 'jane', :last_name => 'doe'},
|
208
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
209
|
+
).to_return(
|
210
|
+
:status => 301,
|
211
|
+
:body => 'redirect',
|
212
|
+
:headers => {'Location' => "https://example.com/members"}
|
213
|
+
)
|
214
|
+
|
215
|
+
stub_post('/members').with(
|
216
|
+
:body => {:first_name => 'jane', :last_name => 'doe'},
|
217
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
218
|
+
).to_return(
|
219
|
+
:status => 200,
|
220
|
+
:body => 'sucess'
|
221
|
+
)
|
222
|
+
|
223
|
+
subject.send_request(:post, '/users', :params => {:first_name => 'jane', :last_name => 'doe'})
|
224
|
+
end
|
225
|
+
|
226
|
+
it "respects the redirect limit " do
|
227
|
+
subject.max_redirects = 1
|
228
|
+
|
229
|
+
stub_post('/users').with(
|
230
|
+
:body => {:first_name => 'jane', :last_name => 'doe'},
|
231
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
232
|
+
).to_return(
|
233
|
+
:status => 301,
|
234
|
+
:body => 'redirect',
|
235
|
+
:headers => {'Location' => "https://example.com/members"}
|
236
|
+
)
|
237
|
+
|
238
|
+
stub_post('/members').with(
|
239
|
+
:body => {:first_name => 'jane', :last_name => 'doe'},
|
240
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
241
|
+
).to_return(
|
242
|
+
:status => 301,
|
243
|
+
:body => 'redirect',
|
244
|
+
:headers => {'Location' => "https://example.com/profiles"}
|
245
|
+
)
|
246
|
+
|
247
|
+
subject.send_request(:post, '/users', :params => {:first_name => 'jane', :last_name => 'doe'})
|
248
|
+
end
|
249
|
+
|
250
|
+
it "modifies http 303 redirect from POST to GET " do
|
251
|
+
|
252
|
+
stub_post('/users').with(
|
253
|
+
:body => {:first_name => 'jane', :last_name => 'doe'},
|
254
|
+
:headers => {'Content-Type' => 'application/x-www-form-urlencoded' }.merge(subject.default_headers)
|
255
|
+
).to_return(
|
256
|
+
:status => 303,
|
257
|
+
:body => 'redirect',
|
258
|
+
:headers => {'Location' => "https://example.com/members"}
|
259
|
+
)
|
260
|
+
|
261
|
+
stub_get('/members').with(
|
262
|
+
:headers => subject.default_headers
|
263
|
+
).to_return(
|
264
|
+
:status => 200,
|
265
|
+
:body => ''
|
266
|
+
)
|
267
|
+
response = subject.send_request(:post, '/users', :params => {:first_name => 'jane', :last_name => 'doe'})
|
268
|
+
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
unless ENV['CI']
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
add_filter 'spec'
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'rspec'
|
9
|
+
require 'rspec/autorun'
|
10
|
+
require 'webmock/rspec'
|
11
|
+
require 'ostruct'
|
12
|
+
require 'simple_http'
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.mock_with :rspec
|
16
|
+
config.expect_with :rspec do |c|
|
17
|
+
c.syntax = :expect
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def stub_delete(path='')
|
22
|
+
stub_request(:delete, "https://example.com:443#{path}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_get(path='')
|
26
|
+
stub_request(:get, "https://example.com:443#{path}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def stub_post(path='')
|
30
|
+
stub_request(:post, "https://example.com:443#{path}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def stub_put(path='')
|
34
|
+
stub_request(:put, "https://example.com:443#{path}")
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_http
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kevin Mutyaba
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
- !binary |-
|
13
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURjRENDQWxpZ0F3SUJB
|
14
|
+
Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREEvTVJFd0R3WURWUVFEREFoMGFX
|
15
|
+
RmkKWVhOdWF6RVZNQk1HQ2dtU0pvbVQ4aXhrQVJrV0JXZHRZV2xzTVJNd0VR
|
16
|
+
WUtDWkltaVpQeUxHUUJHUllEWTI5dApNQjRYRFRFek1ETXdNekEyTWpBeE5W
|
17
|
+
b1hEVEUwTURNd016QTJNakF4TlZvd1B6RVJNQThHQTFVRUF3d0lkR2xoCllt
|
18
|
+
RnpibXN4RlRBVEJnb0praWFKay9Jc1pBRVpGZ1ZuYldGcGJERVRNQkVHQ2dt
|
19
|
+
U0pvbVQ4aXhrQVJrV0EyTnYKYlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFB
|
20
|
+
RGdnRVBBRENDQVFvQ2dnRUJBTXNtVnNFcmNOdXdRTEtMaDlUNgphNTdRaUsz
|
21
|
+
NWc5empwSUQycFVCbjRhbE1UbUllQVhnMmJYV0xkQXpVMHN3Y2ptYUdCV3o1
|
22
|
+
QWFaZXFUbm5CdmVPClpEb0g2ZTgxMXV1UmpKTVlDa0xReGhsZ2hFQjBUUWtB
|
23
|
+
cU9ueGxqODBUTjJqRncrWUZXTG1TbnhSNFBCb252cHAKWXdXQVkweWxxTTU0
|
24
|
+
RlBSaGFBSVlDNS8zUHZ4MVNZTDkvVXMwMzc2SEVwVjBSdHk2Vlh6N3RVenY4
|
25
|
+
dkZraTVvdApneWZwNWNlV2lZSVpqUTlVdmhtNGx1SlNmWGNpMTNVSFowQWVP
|
26
|
+
N0UxcGFkV2x4M3o4aFpJdmphd3VlVEdSZTVwCkJnWmxJMCt4VjJvZ3ZBbHU4
|
27
|
+
L05DeTBoV1V3Y3BudlJkUHlCVkRSTWxpOGdYR0U5ak52OGRCV2U2N3ZkanpH
|
28
|
+
U2sKWURVQ0F3RUFBYU4zTUhVd0NRWURWUjBUQkFJd0FEQUxCZ05WSFE4RUJB
|
29
|
+
TUNCTEF3SFFZRFZSME9CQllFRkluaApxdkprdUlTTnFET2NzckJSb3RaQzBx
|
30
|
+
b2xNQjBHQTFVZEVRUVdNQlNCRW5ScFlXSmhjMjVyUUdkdFlXbHNMbU52CmJU
|
31
|
+
QWRCZ05WSFJJRUZqQVVnUkowYVdGaVlYTnVhMEJuYldGcGJDNWpiMjB3RFFZ
|
32
|
+
SktvWklodmNOQVFFRkJRQUQKZ2dFQkFFR2I0Z1JEdWxKOWprZjVvUkx5ZGZ3
|
33
|
+
OVVaaTZmVldqNmFhaUpmYmJUNU5Mb3RwVmFXbldkQ09PN2h5OApIRFBZV040
|
34
|
+
MzB6THdyME9ET1U5WE51ZUtuRWtobkJSaVlrY1EwSm1ZZGRQa0w1N2twMHFs
|
35
|
+
SDRnMklxUWZRVjJXCjFiN3NFNDEwekZIbjU1QjVuaWhRWTNjME1NU0w3d3E5
|
36
|
+
RHoyRWt0YklNaWtmNnNHNnpmVWdZRkU0SVFHaTJSYk8KeGE1Zm5UV3Q3S0I1
|
37
|
+
REQwMkhuSExUWjlIbDJreGxQeVd3eWpSRXdOd0VqUG9TVUpGRUJpb3N2QW1s
|
38
|
+
OGZyVURBOQpqNmZBVGcvNGZxcGdJTFBWcUZJR1pPTUpERmNKeS9vZWh3d3hM
|
39
|
+
dTVYTXg4OFdGRDlqVDF2Umo3N0Q3aVBMYlhkCnJmR3MvcUNKS2dpZlhkLzFh
|
40
|
+
bTVobEFINWpYVT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
41
|
+
date: 2013-03-17 00:00:00.000000000 Z
|
42
|
+
dependencies:
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: rake
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rspec
|
61
|
+
requirement: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: simplecov
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.7.1
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ~>
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 0.7.1
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: webmock
|
93
|
+
requirement: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.9.0
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ~>
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.9.0
|
107
|
+
description: A Net::HTTP wrapper
|
108
|
+
email:
|
109
|
+
- tiabasnk@gmail.com
|
110
|
+
executables: []
|
111
|
+
extensions: []
|
112
|
+
extra_rdoc_files: []
|
113
|
+
files:
|
114
|
+
- .gitignore
|
115
|
+
- .travis.yml
|
116
|
+
- CHANGELOG.md
|
117
|
+
- Gemfile
|
118
|
+
- LICENSE
|
119
|
+
- README.md
|
120
|
+
- Rakefile
|
121
|
+
- certs/tiabas_public.pem
|
122
|
+
- lib/simple_http.rb
|
123
|
+
- lib/simple_http/connection.rb
|
124
|
+
- lib/simple_http/version.rb
|
125
|
+
- simple_http.gemspec
|
126
|
+
- spec/connection_spec.rb
|
127
|
+
- spec/spec_helper.rb
|
128
|
+
homepage: ''
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ! '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 1.8.25
|
150
|
+
signing_key:
|
151
|
+
specification_version: 3
|
152
|
+
summary: Simple HTTP wrapper for Ruby
|
153
|
+
test_files:
|
154
|
+
- spec/connection_spec.rb
|
155
|
+
- spec/spec_helper.rb
|
metadata.gz.sig
ADDED
Binary file
|