content_gateway 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.
- checksums.yaml +4 -4
- data/Changelog +5 -0
- data/Gemfile.lock +1 -1
- data/LICENSE.txt +22 -0
- data/README.md +24 -2
- data/content-gateway.gemspec +3 -3
- data/lib/content_gateway/cache.rb +1 -0
- data/lib/content_gateway/exceptions.rb +6 -0
- data/lib/content_gateway/gateway.rb +3 -2
- data/lib/content_gateway/request.rb +22 -3
- data/lib/content_gateway/version.rb +1 -1
- data/spec/unit/content_gateway/cache_spec.rb +5 -0
- data/spec/unit/content_gateway/gateway_spec.rb +4 -4
- data/spec/unit/content_gateway/request_spec.rb +52 -0
- metadata +9 -5
- data/COPYING +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07723d5fea288ca91c4f1da7436168e83daa8fea
|
4
|
+
data.tar.gz: d66d49a1846de645acce9b3a2363056c16992842
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45f744929408bf9b41b94a212c9320a152dd9b0a8baa7ed733eb12bb1eb9d9e21de47179d6eedf522a9c30c886740f8ae6ccfe8bba979c720e86f783afab6839
|
7
|
+
data.tar.gz: 39795c45b0a7fcc25619aea6df33cad3d360604b2984a44ac40bd842ff8aaf28e3c35e0350b405a720a802af8f06e30efdab41d8f861a0e0ac78e91fdcf8a957
|
data/Changelog
CHANGED
data/Gemfile.lock
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014, Globo.com - Webmedia
|
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
CHANGED
@@ -85,6 +85,7 @@ Optional parameters are supported:
|
|
85
85
|
- `stale_expires_in`: overwrites the default stale cache expiration time
|
86
86
|
- `skip_cache`: if set to `true`, ignores cache and stale cache
|
87
87
|
- `headers`: a hash with request headers
|
88
|
+
- `ssl_certificate`: a hash with ssl cert and key (see ssl support section below)
|
88
89
|
|
89
90
|
Every other parameter is passed to URLGenerator `generate` method (like query string parameters).
|
90
91
|
|
@@ -100,7 +101,7 @@ gateway.get_json("/path.json", skip_cache: true)
|
|
100
101
|
|
101
102
|
POST, PUT and DELETE verbs are also supported, but ignore cache and stale cache.
|
102
103
|
The gateway object offers the equivalent methods for these verbs (`post`, `post_json`, `put`, `put_json`, `delete` and `delete_json`).
|
103
|
-
The only optional
|
104
|
+
The only optional parameters supported by these methods are `payload` and `ssl_certificate`.
|
104
105
|
Every other parameter is passed to URLGenerator `generate` method (like query string parameters).
|
105
106
|
|
106
107
|
Examples:
|
@@ -113,8 +114,29 @@ gateway.put_json("/api/put_example.json", query_string_param: "value")
|
|
113
114
|
gateway.delete("/api/delete_example", id: "100")
|
114
115
|
```
|
115
116
|
|
117
|
+
### SSL Support
|
118
|
+
|
119
|
+
You can use ssl certificates to run all supported requests (get, post, put, delete).
|
120
|
+
|
121
|
+
Just pass the path of cert file (x509 certificate) and key file (rsa key) to the request method. See exemple below:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
ssl = {
|
125
|
+
ssl_client_cert: "path/client.cert",
|
126
|
+
ssl_client_key: "path/client.key"
|
127
|
+
}
|
128
|
+
|
129
|
+
gateway.get("/path", timeout: 3, ssl_certificate: ssl)
|
130
|
+
|
131
|
+
gateway.get_json("/path.json", skip_cache: true, ssl_certificate: ssl)
|
132
|
+
|
133
|
+
gateway.post("/api/post_example", payload: { param1: "value" }, ssl_certificate: ssl)
|
134
|
+
```
|
135
|
+
|
116
136
|
## Authors
|
117
137
|
|
138
|
+
- [Túlio Ornelas](https://github.com/tulios)
|
139
|
+
- [Roberto Soares](https://github.com/roberto)
|
118
140
|
- [Emerson Macedo](https://github.com/emerleite)
|
119
141
|
- [Guilherme Garnier](https://github.com/ggarnier)
|
120
142
|
- [Daniel Martins](https://github.com/danielfm)
|
@@ -131,4 +153,4 @@ gateway.delete("/api/delete_example", id: "100")
|
|
131
153
|
|
132
154
|
## License
|
133
155
|
|
134
|
-
Copyright (c) 2014 Globo.com - Webmedia. See [
|
156
|
+
Copyright (c) 2014 Globo.com - Webmedia. See [LICENSE.txt](https://github.com/globocom/content-gateway-ruby/blob/master/LICENSE.txt) for more details.
|
data/content-gateway.gemspec
CHANGED
@@ -5,11 +5,11 @@ require 'content_gateway/version'
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
6
|
gem.name = "content_gateway"
|
7
7
|
gem.version = ContentGateway::VERSION
|
8
|
-
gem.authors = ["Emerson Macedo", "Guilherme Garnier", "Daniel Martins", "Rafael Biriba", "Célio Latorraca"]
|
9
|
-
gem.email = ["emerleite@gmail.com", "guilherme.garnier@gmail.com", "daniel.tritone@gmail.com", "biribarj@gmail.com", "celio.la@gmail.com"]
|
8
|
+
gem.authors = ["Túlio Ornelas", "Roberto Soares", "Emerson Macedo", "Guilherme Garnier", "Daniel Martins", "Rafael Biriba", "Célio Latorraca"]
|
9
|
+
gem.email = ["ornelas.tulio@gmail.com", "roberto.tech@gmail.com", "emerleite@gmail.com", "guilherme.garnier@gmail.com", "daniel.tritone@gmail.com", "biribarj@gmail.com", "celio.la@gmail.com"]
|
10
10
|
gem.description = %q{An easy way to get external content with two cache levels. The first is a performance cache and second is the stale}
|
11
11
|
gem.summary = %q{Content Gateway}
|
12
|
-
gem.homepage = ""
|
12
|
+
gem.homepage = "https://github.com/globocom/content-gateway-ruby"
|
13
13
|
|
14
14
|
gem.files = `git ls-files`.split($/)
|
15
15
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -23,6 +23,7 @@ module ContentGateway
|
|
23
23
|
@config.cache.fetch(@url, expires_in: expires_in) do
|
24
24
|
@status = "MISS"
|
25
25
|
response = request.execute
|
26
|
+
response = String.new(response) if response
|
26
27
|
|
27
28
|
@config.cache.write(stale_key, response, expires_in: stale_expires_in)
|
28
29
|
response
|
@@ -75,5 +75,11 @@ module ContentGateway
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
class OpenSSLFailure < BaseError
|
79
|
+
def initialize(resource_url, wrapped_exception = nil, info=nil)
|
80
|
+
super(resource_url, wrapped_exception, 406, info)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
78
84
|
class StaleCacheNotAvailableError < StandardError; end
|
79
85
|
end
|
@@ -20,7 +20,8 @@ module ContentGateway
|
|
20
20
|
data = { method: :get, url: url }.tap do |h|
|
21
21
|
h[:headers] = headers if headers.present?
|
22
22
|
end
|
23
|
-
|
23
|
+
request_params = { skip_cache: skip_cache, expires_in: expires_in, stale_expires_in: stale_expires_in, timeout: timeout }.merge(params)
|
24
|
+
send_request(data, request_params)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
@@ -80,7 +81,7 @@ module ContentGateway
|
|
80
81
|
payload = request_data[:payload]
|
81
82
|
|
82
83
|
@cache = ContentGateway::Cache.new(@config, url, method, params)
|
83
|
-
@request = ContentGateway::Request.new(method, url, headers, payload, @config.try(:proxy))
|
84
|
+
@request = ContentGateway::Request.new(method, url, headers, payload, @config.try(:proxy), params)
|
84
85
|
|
85
86
|
begin
|
86
87
|
do_request(params)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module ContentGateway
|
2
2
|
class Request
|
3
|
-
def initialize(method, url, headers = {}, payload = {}, proxy = nil)
|
3
|
+
def initialize(method, url, headers = {}, payload = {}, proxy = nil, params = {})
|
4
4
|
data = { method: method, url: url, proxy: proxy || :none }.tap do |h|
|
5
5
|
h[:payload] = payload if payload.present?
|
6
6
|
h[:headers] = headers if headers.present?
|
7
|
+
h = load_ssl_params(h, params) if params.has_key?(:ssl_certificate)
|
7
8
|
end
|
8
|
-
|
9
9
|
@client = RestClient::Request.new(data)
|
10
10
|
end
|
11
11
|
|
@@ -29,7 +29,7 @@ module ContentGateway
|
|
29
29
|
|
30
30
|
rescue RestClient::Exception => e6
|
31
31
|
status_code = e6.http_code
|
32
|
-
if status_code < 500
|
32
|
+
if status_code && status_code < 500
|
33
33
|
raise e6
|
34
34
|
else
|
35
35
|
raise ContentGateway::ServerError.new url, e6, status_code
|
@@ -41,6 +41,25 @@ module ContentGateway
|
|
41
41
|
|
42
42
|
private
|
43
43
|
|
44
|
+
def load_ssl_params h, params
|
45
|
+
client_cert_file = File.read params[:ssl_certificate][:ssl_client_cert]
|
46
|
+
client_cert_key = File.read params[:ssl_certificate][:ssl_client_key]
|
47
|
+
|
48
|
+
h[:ssl_client_cert] = OpenSSL::X509::Certificate.new(client_cert_file)
|
49
|
+
h[:ssl_client_key] = OpenSSL::PKey::RSA.new(client_cert_key)
|
50
|
+
h[:verify_ssl] = OpenSSL::SSL::VERIFY_NONE
|
51
|
+
h
|
52
|
+
|
53
|
+
rescue Errno::ENOENT => e0
|
54
|
+
raise ContentGateway::OpenSSLFailure.new h[:url], e0
|
55
|
+
|
56
|
+
rescue OpenSSL::X509::CertificateError => e1
|
57
|
+
raise ContentGateway::OpenSSLFailure.new h[:url], e1, "invalid ssl client cert"
|
58
|
+
|
59
|
+
rescue OpenSSL::PKey::RSAError => e2
|
60
|
+
raise ContentGateway::OpenSSLFailure.new h[:url], e2, "invalid ssl client key"
|
61
|
+
end
|
62
|
+
|
44
63
|
def url
|
45
64
|
@client.url
|
46
65
|
end
|
@@ -84,6 +84,11 @@ describe ContentGateway::Cache do
|
|
84
84
|
expect(subject.status).to eql "MISS"
|
85
85
|
end
|
86
86
|
|
87
|
+
it "should convert request response into string" do
|
88
|
+
expect(String).to receive(:new).with("data")
|
89
|
+
subject.fetch(request)
|
90
|
+
end
|
91
|
+
|
87
92
|
it "should return the request data" do
|
88
93
|
expect(subject.fetch(request)).to eql "data"
|
89
94
|
end
|
@@ -23,7 +23,7 @@ describe ContentGateway::Gateway do
|
|
23
23
|
before do
|
24
24
|
expect(ContentGateway::Request).
|
25
25
|
to receive(:new).
|
26
|
-
with(:get, "url", headers, nil, config.proxy).
|
26
|
+
with(:get, "url", headers, nil, config.proxy, cache_params).
|
27
27
|
and_return(request)
|
28
28
|
expect(ContentGateway::Cache).
|
29
29
|
to receive(:new).
|
@@ -48,7 +48,7 @@ describe ContentGateway::Gateway do
|
|
48
48
|
before do
|
49
49
|
expect(ContentGateway::Request).
|
50
50
|
to receive(:new).
|
51
|
-
with(:post, "url", nil, payload, config.proxy).
|
51
|
+
with(:post, "url", nil, payload, config.proxy, cache_params).
|
52
52
|
and_return(request)
|
53
53
|
expect(ContentGateway::Cache).
|
54
54
|
to receive(:new).
|
@@ -73,7 +73,7 @@ describe ContentGateway::Gateway do
|
|
73
73
|
before do
|
74
74
|
expect(ContentGateway::Request).
|
75
75
|
to receive(:new).
|
76
|
-
with(:put, "url", nil, payload, config.proxy).
|
76
|
+
with(:put, "url", nil, payload, config.proxy, cache_params).
|
77
77
|
and_return(request)
|
78
78
|
expect(ContentGateway::Cache).
|
79
79
|
to receive(:new).
|
@@ -98,7 +98,7 @@ describe ContentGateway::Gateway do
|
|
98
98
|
before do
|
99
99
|
expect(ContentGateway::Request).
|
100
100
|
to receive(:new).
|
101
|
-
with(:delete, "url", nil, payload, config.proxy).
|
101
|
+
with(:delete, "url", nil, payload, config.proxy, cache_params).
|
102
102
|
and_return(request)
|
103
103
|
expect(ContentGateway::Cache).
|
104
104
|
to receive(:new).
|
@@ -101,5 +101,57 @@ describe ContentGateway::Request do
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
104
|
+
|
105
|
+
context "requests with SSL" do
|
106
|
+
|
107
|
+
let(:ssl_certificate_params) { { ssl_client_cert: "test", ssl_client_key: "test"} }
|
108
|
+
let(:restclient_ssl_params) { { :ssl_client_cert=>"cert", :ssl_client_key=>"key", :verify_ssl=>0 } }
|
109
|
+
let(:request_params_ssl) { request_params.merge! restclient_ssl_params }
|
110
|
+
|
111
|
+
let :subject_ssl do
|
112
|
+
ContentGateway::Request.new(:get, "/url", {}, {}, nil, ssl_certificate: ssl_certificate_params)
|
113
|
+
end
|
114
|
+
|
115
|
+
context "when request is successful" do
|
116
|
+
before do
|
117
|
+
allow(File).to receive(:read).with("test").and_return("cert_content")
|
118
|
+
allow(OpenSSL::X509::Certificate).to receive(:new).with("cert_content").and_return("cert")
|
119
|
+
allow(OpenSSL::PKey::RSA).to receive(:new).with("cert_content").and_return("key")
|
120
|
+
allow(RestClient::Request).to receive(:new).with(request_params_ssl).and_return(client)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should setup ssl certificates" do
|
124
|
+
expect(OpenSSL::X509::Certificate).to receive(:new).with("cert_content")
|
125
|
+
expect(OpenSSL::PKey::RSA).to receive(:new).with("cert_content")
|
126
|
+
subject_ssl.execute
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should setup request with ssl params" do
|
130
|
+
expect(RestClient::Request).to receive(:new).with(request_params_ssl)
|
131
|
+
subject_ssl.execute
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should return request data with ssl params" do
|
135
|
+
expect(subject_ssl.execute).to eql "data"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "when request fails" do
|
140
|
+
it "should return ssl failure error if certificate was not found" do
|
141
|
+
expect { subject_ssl.execute }.to raise_error(ContentGateway::OpenSSLFailure).with_message("/url - No such file or directory - test")
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should return ssl failure error if certificate cert was not valid" do
|
145
|
+
allow(File).to receive(:read).with("test").and_return("cert_content")
|
146
|
+
expect { subject_ssl.execute }.to raise_error(ContentGateway::OpenSSLFailure).with_message("/url - not enough data - invalid ssl client cert")
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should return ssl failure error if certificate key was not valid" do
|
150
|
+
allow(File).to receive(:read).with("test").and_return("cert_content")
|
151
|
+
allow(OpenSSL::X509::Certificate).to receive(:new).with("cert_content").and_return("cert")
|
152
|
+
expect { subject_ssl.execute }.to raise_error(ContentGateway::OpenSSLFailure).with_message("/url - Neither PUB key nor PRIV key: not enough data - invalid ssl client key")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
104
156
|
end
|
105
157
|
end
|
metadata
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: content_gateway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
+
- Túlio Ornelas
|
8
|
+
- Roberto Soares
|
7
9
|
- Emerson Macedo
|
8
10
|
- Guilherme Garnier
|
9
11
|
- Daniel Martins
|
@@ -12,7 +14,7 @@ authors:
|
|
12
14
|
autorequire:
|
13
15
|
bindir: bin
|
14
16
|
cert_chain: []
|
15
|
-
date: 2014-10-
|
17
|
+
date: 2014-10-31 00:00:00.000000000 Z
|
16
18
|
dependencies:
|
17
19
|
- !ruby/object:Gem::Dependency
|
18
20
|
name: activesupport
|
@@ -101,6 +103,8 @@ dependencies:
|
|
101
103
|
description: An easy way to get external content with two cache levels. The first
|
102
104
|
is a performance cache and second is the stale
|
103
105
|
email:
|
106
|
+
- ornelas.tulio@gmail.com
|
107
|
+
- roberto.tech@gmail.com
|
104
108
|
- emerleite@gmail.com
|
105
109
|
- guilherme.garnier@gmail.com
|
106
110
|
- daniel.tritone@gmail.com
|
@@ -114,10 +118,10 @@ files:
|
|
114
118
|
- .rspec
|
115
119
|
- .ruby-gemset
|
116
120
|
- .ruby-version
|
117
|
-
- COPYING
|
118
121
|
- Changelog
|
119
122
|
- Gemfile
|
120
123
|
- Gemfile.lock
|
124
|
+
- LICENSE.txt
|
121
125
|
- README.md
|
122
126
|
- Rakefile
|
123
127
|
- content-gateway.gemspec
|
@@ -132,7 +136,7 @@ files:
|
|
132
136
|
- spec/unit/content_gateway/cache_spec.rb
|
133
137
|
- spec/unit/content_gateway/gateway_spec.rb
|
134
138
|
- spec/unit/content_gateway/request_spec.rb
|
135
|
-
homepage:
|
139
|
+
homepage: https://github.com/globocom/content-gateway-ruby
|
136
140
|
licenses: []
|
137
141
|
metadata: {}
|
138
142
|
post_install_message:
|
@@ -151,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
155
|
version: '0'
|
152
156
|
requirements: []
|
153
157
|
rubyforge_project:
|
154
|
-
rubygems_version: 2.
|
158
|
+
rubygems_version: 2.1.11
|
155
159
|
signing_key:
|
156
160
|
specification_version: 4
|
157
161
|
summary: Content Gateway
|
data/COPYING
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
Copyright (c) 2014, Globo.com - Webmedia
|
2
|
-
All rights reserved.
|
3
|
-
|
4
|
-
Redistribution and use in source and binary forms, with or without
|
5
|
-
modification, are permitted provided that the following conditions are met:
|
6
|
-
* Redistributions of source code must retain the above copyright
|
7
|
-
notice, this list of conditions and the following disclaimer.
|
8
|
-
* Redistributions in binary form must reproduce the above copyright
|
9
|
-
notice, this list of conditions and the following disclaimer in the
|
10
|
-
documentation and/or other materials provided with the distribution.
|
11
|
-
* Neither the name of the Globo.com - Webmedia nor the
|
12
|
-
names of its contributors may be used to endorse or promote products
|
13
|
-
derived from this software without specific prior written permission.
|
14
|
-
|
15
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
16
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
-
DISCLAIMED. IN NO EVENT SHALL GLOBO.COM - WEBMEDIA BE LIABLE FOR ANY
|
19
|
-
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
-
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|