resource_accessor 1.1.0 → 1.1.1
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/CHANGES +5 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/lib/resource_accessor/resource_accessor.rb +7 -0
- data/lib/resource_accessor/version.rb +1 -1
- data/spec/gateway_spec.rb +188 -0
- data/spec/resource_accessor_spec.rb +9 -1
- data/spec/spec_helper.rb +9 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f6eb7b46ad736c090bf61416ff239b6f39254d3
|
4
|
+
data.tar.gz: 5415d79f310c60cdce46f42666878c834d335cbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d979406e639d945bde47697aea567afefd11e3014bb581789552ef0d67fd4070e092b45b0454131c7ee4f288b35ce618c59c2210f5a44740b606b1b2e0436158
|
7
|
+
data.tar.gz: db397ac1b3f05c92f69674fbf4f81f4f2858d518fe148d6fb7021cece49138a00b26f4aa77f6f10ffae85973f06fb333d59b562c5d55a23e9d303b03fc5b7aef
|
data/CHANGES
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'net/https'
|
2
|
+
require 'cgi'
|
2
3
|
|
3
4
|
class ResourceAccessor
|
4
5
|
attr_accessor :timeout, :ca_file, :validate_ssl_cert
|
@@ -43,6 +44,12 @@ class ResourceAccessor
|
|
43
44
|
response.response['set-cookie']
|
44
45
|
end
|
45
46
|
|
47
|
+
def query_from_hash(params)
|
48
|
+
return "" if params.empty?
|
49
|
+
|
50
|
+
params.sort.map {|k, v| "#{k}=#{v.nil? ? '' : CGI.escape(v)}"}.join("&")
|
51
|
+
end
|
52
|
+
|
46
53
|
private
|
47
54
|
|
48
55
|
def locate_response url, method, headers, body, cookie=nil
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
GatewayError = Class.new(Exception)
|
4
|
+
|
5
|
+
require 'resource_accessor'
|
6
|
+
require 'log4r'
|
7
|
+
|
8
|
+
class Gateway
|
9
|
+
include Log4r
|
10
|
+
|
11
|
+
attr_accessor :accessor, :logger
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@accessor = ResourceAccessor.new
|
15
|
+
@accessor.timeout = 30
|
16
|
+
|
17
|
+
@logger = Logger.new 'my_logger'
|
18
|
+
#@logger.outputters = Outputter.stdout
|
19
|
+
end
|
20
|
+
|
21
|
+
def bad_response? response
|
22
|
+
response.class == Net::HTTPNotFound or (response.kind_of?(Net::HTTPSuccess) and !!(response.body =~/error/))
|
23
|
+
end
|
24
|
+
|
25
|
+
def get params = {}, headers = {}
|
26
|
+
with_exception_handler(params, headers) do |params, headers|
|
27
|
+
@accessor.get_response(params, headers)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def post params = {}, headers = {}
|
32
|
+
with_exception_handler(params, headers) do |params, headers|
|
33
|
+
@accessor.get_response(params.merge(:method => :post), headers)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def soap_post params = {}, headers = {}
|
38
|
+
with_exception_handler(params, headers) do |params, headers|
|
39
|
+
response = @accessor.get_soap_response(params.merge(:method => :post), headers)
|
40
|
+
|
41
|
+
logger.debug "#{params[:body]}" if params[:body]
|
42
|
+
|
43
|
+
response
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def with_exception_handler params, headers, &code
|
48
|
+
begin
|
49
|
+
response = code.call(params, headers)
|
50
|
+
|
51
|
+
if bad_response?(response)
|
52
|
+
log.error(response, "#{self.class.name} failed with #{response.code}:#{response.message}\n#{response.body}")
|
53
|
+
|
54
|
+
raise GatewayError, "#{response.code} #{response.message}\n#{response.body}\n(URL: '#{params[:url]}')"
|
55
|
+
else
|
56
|
+
logger.info("Got #{response.code} response from #{self.class.name} Service")
|
57
|
+
end
|
58
|
+
rescue GatewayError
|
59
|
+
raise
|
60
|
+
rescue Exception => e
|
61
|
+
logger.error("#{self.class.name} received error: #{e}")
|
62
|
+
|
63
|
+
raise GatewayError, "Error: #{e} (URL: '#{params[:url]}')"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Gateway do
|
69
|
+
let(:some_https_url) { "https://somehost.com" }
|
70
|
+
|
71
|
+
let(:simple_response) do
|
72
|
+
good_response = Net::HTTPSuccess.new "1.1", "200", "success"
|
73
|
+
good_response.stubs(:stream_check => '')
|
74
|
+
good_response
|
75
|
+
end
|
76
|
+
|
77
|
+
it "uses certificate file and OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT as verify mode if validate_ssl_cert is on" do
|
78
|
+
subject.accessor.validate_ssl_cert = true
|
79
|
+
subject.accessor.ca_file = 'some_ca_file'
|
80
|
+
|
81
|
+
Net::HTTP.any_instance.expects(:use_ssl=).with(true)
|
82
|
+
Net::HTTP.any_instance.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT)
|
83
|
+
Net::HTTP.any_instance.expects(:ca_file=).with('some_ca_file')
|
84
|
+
|
85
|
+
Timeout.expects(:timeout).yields
|
86
|
+
Net::HTTP.any_instance.stubs(:request).returns(stub_everything(:kind_of? => true))
|
87
|
+
|
88
|
+
subject.get(:url => some_https_url)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "uses VERIFY_NONE to enforce certificate validation" do
|
92
|
+
subject.accessor.validate_ssl_cert = false
|
93
|
+
subject.accessor.ca_file = 'some_ca_file'
|
94
|
+
|
95
|
+
Net::HTTP.any_instance.expects(:use_ssl=).with(true)
|
96
|
+
Net::HTTP.any_instance.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
|
97
|
+
Net::HTTP.any_instance.expects(:ca_file=).with('some_ca_file').never
|
98
|
+
|
99
|
+
Timeout.expects(:timeout).yields
|
100
|
+
Net::HTTP.any_instance.stubs(:request).returns(stub_everything(:kind_of? => true))
|
101
|
+
|
102
|
+
subject.get(:url => some_https_url)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "logs error and raises exception if response is bad" do
|
106
|
+
Timeout.expects(:timeout).yields
|
107
|
+
Net::HTTP.any_instance.expects(:request).returns(simple_response)
|
108
|
+
|
109
|
+
subject.stubs(:bad_response? => true)
|
110
|
+
|
111
|
+
subject.logger.expects(:error)
|
112
|
+
|
113
|
+
expect do
|
114
|
+
subject.soap_post(:url => some_https_url, :body => 'body')
|
115
|
+
end.to raise_error(GatewayError)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should set content type to text/xml for soap post request" do
|
119
|
+
Net::HTTP.any_instance.expects(:request).returns(simple_response)
|
120
|
+
|
121
|
+
Timeout.expects(:timeout).yields
|
122
|
+
|
123
|
+
params = {:url => some_https_url}
|
124
|
+
headers = {}
|
125
|
+
|
126
|
+
subject.soap_post(params, headers)
|
127
|
+
|
128
|
+
headers["Content-Type"].should match "text/xml"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should set content type to application/x-www-form-urlencoded for regular post request" do
|
132
|
+
post_request = Net::HTTP::Post.new 'someurl.com'
|
133
|
+
Net::HTTP::Post.expects(:new).returns(post_request)
|
134
|
+
|
135
|
+
Net::HTTP.any_instance.expects(:request => simple_response)
|
136
|
+
|
137
|
+
Timeout.expects(:timeout).yields
|
138
|
+
|
139
|
+
params = {:url => some_https_url}
|
140
|
+
headers = {}
|
141
|
+
|
142
|
+
subject.post(params, headers)
|
143
|
+
|
144
|
+
headers["Content-Type"].should match "application/x-www-form-urlencoded"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should log timeout errors and raise GatewayError" do
|
148
|
+
subject.logger.expects(:error).with("#{subject.class.name} received error: Timeout::Error")
|
149
|
+
Net::HTTP.any_instance.expects(:request).raises(Timeout::Error.new(nil))
|
150
|
+
|
151
|
+
Timeout.expects(:timeout).yields
|
152
|
+
|
153
|
+
expect do
|
154
|
+
subject.soap_post(:url => some_https_url, :body => 'body')
|
155
|
+
end.to raise_error(GatewayError)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "logs SocketError and raises GatewayError when service not found" do
|
159
|
+
subject.logger.expects(:error).with("#{subject.class.name} received error: SocketError")
|
160
|
+
|
161
|
+
Net::HTTP.any_instance.expects(:request).raises(SocketError)
|
162
|
+
Timeout.expects(:timeout).yields
|
163
|
+
|
164
|
+
expect do
|
165
|
+
subject.get(:url => some_https_url, :body => '')
|
166
|
+
end.to raise_error(GatewayError)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "logs Errno::ECONNRESET and raises GatewayError when service connection reset" do
|
170
|
+
subject.logger.expects(:error).with("#{subject.class.name} received error: Connection reset by peer")
|
171
|
+
|
172
|
+
Net::HTTP.any_instance.expects(:request).raises(Errno::ECONNRESET)
|
173
|
+
Timeout.expects(:timeout).yields
|
174
|
+
|
175
|
+
expect do
|
176
|
+
subject.get(:url => some_https_url, :body => '')
|
177
|
+
end.to raise_error(GatewayError)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "logs body of request" do
|
181
|
+
Net::HTTP.any_instance.expects(:request).returns(simple_response)
|
182
|
+
|
183
|
+
subject.logger.expects(:debug).with('some_request')
|
184
|
+
|
185
|
+
subject.soap_post(:url => some_https_url, :body => 'some_request')
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
2
|
|
3
|
-
require 'resource_accessor
|
3
|
+
require 'resource_accessor'
|
4
4
|
|
5
5
|
describe ResourceAccessor do
|
6
6
|
|
@@ -10,5 +10,13 @@ describe ResourceAccessor do
|
|
10
10
|
response.should_not be_nil
|
11
11
|
end
|
12
12
|
|
13
|
+
it "query_string_from_hash escapes ampersands and spaces in values" do
|
14
|
+
subject.query_from_hash({'name1' => "name 1", 'name2' => "name 2"}).should eql "name1=name+1&name2=name+2"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "query_string_from_hash maps properly nil values " do
|
18
|
+
subject.query_from_hash({'param1' => nil, 'param2' => "A&B", 'param3' => "C & D"}).should eql "param1=¶m2=A%26B¶m3=C+%26+D"
|
19
|
+
end
|
20
|
+
|
13
21
|
end
|
14
22
|
|
data/spec/spec_helper.rb
CHANGED
@@ -3,4 +3,13 @@ require 'rspec'
|
|
3
3
|
# add lib directory
|
4
4
|
$:.unshift File.dirname(__FILE__) + '/../lib'
|
5
5
|
|
6
|
+
RSpec.configure do |config|
|
7
|
+
# ## Mock Framework
|
8
|
+
#
|
9
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
10
|
+
|
11
|
+
config.mock_with :mocha
|
12
|
+
end
|
13
|
+
|
14
|
+
|
6
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resource_accessor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Shvets
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gemspec_deps_gen
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/resource_accessor/version.rb
|
62
62
|
- resource_accessor.gemspec
|
63
63
|
- resource_accessor.gemspec.erb
|
64
|
+
- spec/gateway_spec.rb
|
64
65
|
- spec/resource_accessor_spec.rb
|
65
66
|
- spec/spec_helper.rb
|
66
67
|
homepage: http://github.com/shvets/resource_accessor
|
@@ -83,11 +84,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
84
|
version: '0'
|
84
85
|
requirements: []
|
85
86
|
rubyforge_project:
|
86
|
-
rubygems_version: 2.0.
|
87
|
+
rubygems_version: 2.0.5
|
87
88
|
signing_key:
|
88
89
|
specification_version: 4
|
89
90
|
summary: This library is used to simplify access to protected or unprotected http
|
90
91
|
resource
|
91
92
|
test_files:
|
93
|
+
- spec/gateway_spec.rb
|
92
94
|
- spec/resource_accessor_spec.rb
|
93
95
|
- spec/spec_helper.rb
|