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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65fe5be0eff06af34c50732980238a937d3f8249
4
- data.tar.gz: edd6943756c0136824ba2fefa40768e6c83fa0bd
3
+ metadata.gz: 07723d5fea288ca91c4f1da7436168e83daa8fea
4
+ data.tar.gz: d66d49a1846de645acce9b3a2363056c16992842
5
5
  SHA512:
6
- metadata.gz: 4183a37c2624be76daa48c6f8238e10db77a260903583e2e4bb92123e238e3ed357d5b0393c2de56d3b723f1dc733419c0747b73aef25615a5ed14dcb03cf64c
7
- data.tar.gz: 0405a719b4a119bcc110d6eb077b3f962a1a5d7fd0673110c348c1a713bc2cf575ef4865c4011c7e97fa330e4eb4598d1b649a502ef111d922cb909922d868c1
6
+ metadata.gz: 45f744929408bf9b41b94a212c9320a152dd9b0a8baa7ed733eb12bb1eb9d9e21de47179d6eedf522a9c30c886740f8ae6ccfe8bba979c720e86f783afab6839
7
+ data.tar.gz: 39795c45b0a7fcc25619aea6df33cad3d360604b2984a44ac40bd842ff8aaf28e3c35e0350b405a720a802af8f06e30efdab41d8f861a0e0ac78e91fdcf8a957
data/Changelog CHANGED
@@ -1,3 +1,8 @@
1
+ 2014-10-31 [0.2.0]
2
+
3
+ * Adding ssl support in requests
4
+ * Solving cache problem when using ssl in requests. The solution was convert the result of the request to string before save the cache value.
5
+
1
6
  2014-10-21 [0.1.0]
2
7
 
3
8
  * Adding delete_json method.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- content_gateway (0.1.0)
4
+ content_gateway (0.2.0)
5
5
  activesupport
6
6
  json
7
7
  rest-client
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 parameter supported by these methods is `payload`.
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 [COPYING](https://github.com/globocom/content_gateway/blob/master/COPYING) for more details.
156
+ Copyright (c) 2014 Globo.com - Webmedia. See [LICENSE.txt](https://github.com/globocom/content-gateway-ruby/blob/master/LICENSE.txt) for more details.
@@ -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
- send_request(data, skip_cache: skip_cache, expires_in: expires_in, stale_expires_in: stale_expires_in, timeout: timeout)
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
@@ -1,3 +1,3 @@
1
1
  module ContentGateway
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  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.1.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-21 00:00:00.000000000 Z
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.4.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.