right_cloud_api_base 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY +10 -3
- data/lib/base/api_manager.rb +1 -4
- data/lib/base/helpers/http_request.rb +1 -2
- data/lib/base/helpers/query_api_patterns.rb +2 -2
- data/lib/base/routines/connection_proxies/net_http_persistent_proxy.rb +10 -7
- data/lib/base/routines/connection_proxy.rb +0 -2
- data/lib/right_cloud_api_base.rb +0 -1
- data/lib/right_cloud_api_base_version.rb +2 -2
- data/spec/routines/connection_proxies/test_net_http_persistent_proxy_spec.rb +2 -1
- metadata +2 -3
- data/lib/base/routines/connection_proxies/right_http_connection_proxy.rb +0 -227
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a15b1f9a44a3084eb718cb87639fb3c96c015157
|
4
|
+
data.tar.gz: 99545b9605f6d1b63c2ad1a138fd3ac614a9a811
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 710087ad760c2ec6b5e553e10848c4e54916f9568b957a28a579d1b1d7ca5613015a7604c58b3b07a43c3bbcd0bfbf5c89b7c08f9bf44761d38f576183a560fb
|
7
|
+
data.tar.gz: 24018fc8b936dc861528452f14e55adc4341297443cd1078c36f9bd03ea1ba359668135ae026e32325dd04633ad1c911ef595b3ce659ffa528f824cfa101f84e
|
data/HISTORY
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
== 2015-03-11, v0.2.2
|
2
|
+
- Fixed "Cannot do block-based chunk gets on S3" issue
|
3
|
+
https://github.com/rightscale/right_aws_api/issues/24
|
4
|
+
|
5
|
+
== 2015-01-23, v0.2.1.1
|
6
|
+
- Removed RightHttpConnection gem related code
|
7
|
+
|
8
|
+
== 2014-11-03, v0.2.1
|
9
|
+
- Fix object._blank? issue for IO objects.
|
10
|
+
|
1
11
|
== 2013-06-28
|
2
12
|
- pre-release candidate created
|
3
13
|
|
4
|
-
== 2014-11-03
|
5
|
-
- Fix object._blank? issue for IO objects.
|
6
|
-
- version bumped to 0.1.1
|
data/lib/base/api_manager.rb
CHANGED
@@ -165,10 +165,7 @@ module RightScale
|
|
165
165
|
#
|
166
166
|
# @option options [String] :connection_proxy
|
167
167
|
# Connection proxy class (when it need to be different from the default one).
|
168
|
-
# Only RightScale::CloudApi::ConnectionProxy::NetHttpPersistentProxy
|
169
|
-
# RightScale::CloudApi::ConnectionProxy::RightHttpConnectionProxy are supported.
|
170
|
-
# The last one requires 'right_http_connection' gem to be manually installed, and it is
|
171
|
-
# not recommended to use because it monkey patches Net::HTTP.
|
168
|
+
# Only RightScale::CloudApi::ConnectionProxy::NetHttpPersistentProxy is supported so far.
|
172
169
|
#
|
173
170
|
# @option options [Integer] :connection_read_timeout
|
174
171
|
# Connection read timeout (in seconds).
|
@@ -83,7 +83,7 @@ module RightScale
|
|
83
83
|
# Create a request
|
84
84
|
@verb = verb.to_s.downcase
|
85
85
|
@path = path
|
86
|
-
@
|
86
|
+
@raw = raw
|
87
87
|
@headers = HTTPHeaders::new(headers)
|
88
88
|
self.body = body
|
89
89
|
end
|
@@ -122,7 +122,6 @@ module RightScale
|
|
122
122
|
file.binmode if file.respond_to?(:binmode)
|
123
123
|
# Fix 'content-length': it must not be bigger than a piece of a File left to be read or a String body size.
|
124
124
|
# Otherwise the connection may behave like crazy causing 4xx or 5xx responses
|
125
|
-
# KD: Make sure this code is used with the patched RightHttpConnection gem (see net_fix.rb)
|
126
125
|
file_size = file.respond_to?(:lstat) ? file.lstat.size : file.size
|
127
126
|
bytes_to_read = [ file_size - file.pos, self['content-length'].first ].compact.map{|v| v.to_i }.sort.first # remove nils then make values Integers
|
128
127
|
if self['content-length'].first._blank? || self['content-length'].first.to_i > bytes_to_read
|
@@ -79,7 +79,7 @@ module RightScale
|
|
79
79
|
#
|
80
80
|
# query_api_pattern 'PutObject', :put, '{:Bucket}/{:Object}',
|
81
81
|
# :body => Utils::MUST_BE_SET,
|
82
|
-
# :headers => { 'content-type' => ['
|
82
|
+
# :headers => { 'content-type' => ['binary/octet-stream'] }
|
83
83
|
# ..
|
84
84
|
# end
|
85
85
|
# end
|
@@ -99,7 +99,7 @@ module RightScale
|
|
99
99
|
#
|
100
100
|
# base.query_api_pattern 'PutObject', :put, '{:Bucket:}/{:Object:}',
|
101
101
|
# :body => Utils::MUST_BE_SET,
|
102
|
-
# :headers => { 'content-type' => ['
|
102
|
+
# :headers => { 'content-type' => ['binary/octet-stream'] }
|
103
103
|
#
|
104
104
|
# base.query_api_pattern 'UploadPartCopy', :put,'{:DestinationBucket}/{:DestinationObject}',
|
105
105
|
# :params => { 'partNumber' => :PartNumber, 'uploadId' => :UploadId },
|
@@ -63,9 +63,9 @@ module RightScale
|
|
63
63
|
begin
|
64
64
|
make_request_with_retries(connection, @data[:connection][:uri], http_request)
|
65
65
|
rescue => e
|
66
|
-
|
66
|
+
fail(ConnectionError, e.message)
|
67
67
|
ensure
|
68
|
-
|
68
|
+
connection.shutdown
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -180,9 +180,12 @@ module RightScale
|
|
180
180
|
# then there is no low level retry is allowed. Otherwise we would need to reset the
|
181
181
|
# IO pointer, etc.
|
182
182
|
connection_retry_count = 0
|
183
|
-
|
184
|
-
|
185
|
-
|
183
|
+
if response.is_a?(Net::HTTPSuccess)
|
184
|
+
set_http_response(response, :skip_body)
|
185
|
+
response.read_body(&block)
|
186
|
+
else
|
187
|
+
set_http_response(response)
|
188
|
+
end
|
186
189
|
end
|
187
190
|
else
|
188
191
|
# Set text response
|
@@ -213,10 +216,10 @@ module RightScale
|
|
213
216
|
#
|
214
217
|
# @return [void]
|
215
218
|
#
|
216
|
-
def set_http_response(response)
|
219
|
+
def set_http_response(response, skip_body=false)
|
217
220
|
@data[:response][:instance] = HTTPResponse.new(
|
218
221
|
response.code,
|
219
|
-
|
222
|
+
skip_body ? nil : response.body,
|
220
223
|
response.to_hash,
|
221
224
|
response
|
222
225
|
)
|
@@ -38,12 +38,10 @@ module RightScale
|
|
38
38
|
def process
|
39
39
|
unless @connection_proxy
|
40
40
|
# Try to use a user defined connection proxy. The options are:
|
41
|
-
# - RightScale::CloudApi::ConnectionProxy::RightHttpConnectionProxy,
|
42
41
|
# - RightScale::CloudApi::ConnectionProxy::NetHttpPersistentProxy
|
43
42
|
connection_proxy_class = data[:options][:connection_proxy]
|
44
43
|
unless connection_proxy_class
|
45
44
|
# If it is not defined then load right_http_connection gem and use it.
|
46
|
-
# connection_proxy_class = ConnectionProxy::RightHttpConnectionProxy
|
47
45
|
connection_proxy_class = RightScale::CloudApi::ConnectionProxy::NetHttpPersistentProxy
|
48
46
|
end
|
49
47
|
@connection_proxy = connection_proxy_class.new
|
data/lib/right_cloud_api_base.rb
CHANGED
@@ -62,7 +62,6 @@ require "base/routines/retry_manager"
|
|
62
62
|
require "base/routines/request_initializer"
|
63
63
|
require "base/routines/request_generator"
|
64
64
|
require "base/routines/connection_proxy"
|
65
|
-
require "base/routines/connection_proxies/right_http_connection_proxy"
|
66
65
|
require "base/routines/connection_proxies/net_http_persistent_proxy"
|
67
66
|
require "base/routines/response_parser"
|
68
67
|
require "base/routines/request_analyzer"
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
20
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
21
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
|
22
|
+
#++`
|
23
23
|
|
24
24
|
# RightScale namespace
|
25
25
|
#
|
@@ -31,7 +31,7 @@ module RightScale
|
|
31
31
|
# CloudApi gem version namespace
|
32
32
|
module VERSION
|
33
33
|
# The gem version
|
34
|
-
STRING = '0.2.
|
34
|
+
STRING = '0.2.2'
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -57,7 +57,8 @@ describe "RightScale::CloudApi::ConnectionProxy::NetHTTPPersistentProxy" do
|
|
57
57
|
before :each do
|
58
58
|
@connection = double(
|
59
59
|
:request => @response,
|
60
|
-
:retry_change_requests= => true
|
60
|
+
:retry_change_requests= => true,
|
61
|
+
:shutdown => true )
|
61
62
|
expect(Net::HTTP::Persistent).to receive(:new).and_return(@connection)
|
62
63
|
end
|
63
64
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_cloud_api_base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RightScale, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -144,7 +144,6 @@ files:
|
|
144
144
|
- lib/base/parsers/sax.rb
|
145
145
|
- lib/base/routines/cache_validator.rb
|
146
146
|
- lib/base/routines/connection_proxies/net_http_persistent_proxy.rb
|
147
|
-
- lib/base/routines/connection_proxies/right_http_connection_proxy.rb
|
148
147
|
- lib/base/routines/connection_proxy.rb
|
149
148
|
- lib/base/routines/request_analyzer.rb
|
150
149
|
- lib/base/routines/request_generator.rb
|
@@ -1,227 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2013 RightScale, Inc.
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# 'Software'), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
-
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
-
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
-
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
-
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
23
|
-
|
24
|
-
module RightScale
|
25
|
-
module CloudApi
|
26
|
-
class ConnectionProxy
|
27
|
-
|
28
|
-
class RightHttpConnectionProxy
|
29
|
-
@@storage = {}
|
30
|
-
|
31
|
-
def self.storage
|
32
|
-
@@storage
|
33
|
-
end
|
34
|
-
|
35
|
-
# Remove dead threads/fibers from the storage
|
36
|
-
def self.clean_storage
|
37
|
-
Utils::remove_dead_fibers_and_threads_from_storage(storage)
|
38
|
-
end
|
39
|
-
|
40
|
-
class Error < CloudApi::Error
|
41
|
-
end
|
42
|
-
|
43
|
-
# Performs an HTTP request.
|
44
|
-
#
|
45
|
-
# @param [Hash] data The API request +data+ storage.
|
46
|
-
# See {RightScale::CloudApi::ApiManager.initialize_api_request_options} code for its explanation.
|
47
|
-
#
|
48
|
-
def request(data)
|
49
|
-
require "right_http_connection"
|
50
|
-
|
51
|
-
@data = data
|
52
|
-
@data[:response] = {}
|
53
|
-
# Create a connection
|
54
|
-
@uri = @data[:connection][:uri].dup
|
55
|
-
|
56
|
-
# Create/Get RightHttpConnection instance
|
57
|
-
remote_endpoint = current_endpoint
|
58
|
-
right_http_connection = current_connection
|
59
|
-
|
60
|
-
# Register a callback to close current connection
|
61
|
-
@data[:callbacks][:close_current_connection] = Proc::new{|reason| close_connection(remote_endpoint, reason); log "Current connection closed: #{reason}" }
|
62
|
-
|
63
|
-
# Create a real HTTP request
|
64
|
-
fake = @data[:request][:instance]
|
65
|
-
http_request = "Net::HTTP::#{fake.verb._camelize}"._constantize::new(fake.path)
|
66
|
-
if fake.is_io?
|
67
|
-
http_request.body_stream = fake.body
|
68
|
-
else
|
69
|
-
http_request.body = fake.body
|
70
|
-
end
|
71
|
-
fake.headers.each{|header, value| http_request[header] = value }
|
72
|
-
fake.raw = http_request
|
73
|
-
|
74
|
-
# Set all the options are suported by RightHttpConnection (if they are)
|
75
|
-
http_connection_data = {
|
76
|
-
:server => @uri.host,
|
77
|
-
:port => @uri.port,
|
78
|
-
:protocol => @uri.scheme,
|
79
|
-
:request => http_request,
|
80
|
-
:exception => ConnectionError
|
81
|
-
}
|
82
|
-
|
83
|
-
# Set all required options
|
84
|
-
http_connection_data[:logger] = @data[:options][:cloud_api_logger].logger
|
85
|
-
http_connection_data[:user_agent] = @data[:options][:connection_user_agent] if @data[:options].has_key?(:connection_user_agent)
|
86
|
-
http_connection_data[:ca_file] = @data[:options][:connection_ca_file] if @data[:options].has_key?(:connection_ca_file)
|
87
|
-
http_connection_data[:http_connection_retry_count] = @data[:options][:connection_retry_count] if @data[:options].has_key?(:connection_retry_count)
|
88
|
-
http_connection_data[:http_connection_read_timeout] = @data[:options][:connection_read_timeout] if @data[:options].has_key?(:connection_read_timeout)
|
89
|
-
http_connection_data[:http_connection_open_timeout] = @data[:options][:connection_open_timeout] if @data[:options].has_key?(:connection_open_timeout)
|
90
|
-
http_connection_data[:http_connection_retry_delay] = @data[:options][:connection_retry_delay] if @data[:options].has_key?(:connection_retry_delay)
|
91
|
-
http_connection_data[:raise_on_timeout] = @data[:options][:abort_on_timeout] if @data[:options][:abort_on_timeout]
|
92
|
-
http_connection_data[:cert] = @data[:credentials][:cert] if @data[:credentials].has_key?(:cert)
|
93
|
-
http_connection_data[:key] = @data[:credentials][:key] if @data[:credentials].has_key?(:key)
|
94
|
-
if @data[:options].has_key?(:connection_verify_mode)
|
95
|
-
http_connection_data[:use_server_auth] = (@data[:options][:connection_verify_mode] != OpenSSL::SSL::VERIFY_NONE)
|
96
|
-
end
|
97
|
-
|
98
|
-
#log "HttpConnection request: #{http_connection_data.inspect}"
|
99
|
-
|
100
|
-
# Make a request:
|
101
|
-
block = @data[:vars][:system][:block]
|
102
|
-
if block
|
103
|
-
# If block is given - pass there all the chunks of a response and stop
|
104
|
-
# (dont do any parsing, analysing etc)
|
105
|
-
#
|
106
|
-
# TRB 9/17/07 Careful - because we are passing in blocks, we get a situation where
|
107
|
-
# an exception may get thrown in the block body (which is high-level
|
108
|
-
# code either here or in the application) but gets caught in the
|
109
|
-
# low-level code of HttpConnection. The solution is not to let any
|
110
|
-
# exception escape the block that we pass to HttpConnection::request.
|
111
|
-
# Exceptions can originate from code directly in the block, or from user
|
112
|
-
# code called in the other block which is passed to response.read_body.
|
113
|
-
#
|
114
|
-
# TODO: the suggested fix for RightHttpConnection if to catch
|
115
|
-
# Interrupt and SystemCallError instead of Exception in line 402
|
116
|
-
response = nil
|
117
|
-
begin
|
118
|
-
block_exception = nil
|
119
|
-
# Response.body will be a Net::ReadAdapter instance here - it cant be read as a string.
|
120
|
-
# WEB: On its own, Net::HTTP causes response.body to be a Net::ReadAdapter when you make a request with a block
|
121
|
-
# that calls read_body on the response.
|
122
|
-
response = right_http_connection.request(http_connection_data) do |res|
|
123
|
-
begin
|
124
|
-
# Update temp response
|
125
|
-
@data[:response][:instance] = HTTPResponse::new( res.code,
|
126
|
-
nil,
|
127
|
-
res.to_hash,
|
128
|
-
res )
|
129
|
-
res.read_body(&block) if res.is_a?(Net::HTTPSuccess)
|
130
|
-
rescue Exception => e
|
131
|
-
block_exception = e
|
132
|
-
break
|
133
|
-
end
|
134
|
-
end
|
135
|
-
raise block_exception if block_exception
|
136
|
-
rescue Exception => e
|
137
|
-
right_http_connection.finish(e.message)
|
138
|
-
raise e
|
139
|
-
end
|
140
|
-
else
|
141
|
-
# Things are simple if there is no any block
|
142
|
-
response = right_http_connection.request(http_connection_data)
|
143
|
-
end
|
144
|
-
|
145
|
-
@data[:response][:instance] = HTTPResponse::new( response.code,
|
146
|
-
response.body,
|
147
|
-
response.to_hash,
|
148
|
-
response )
|
149
|
-
|
150
|
-
# # HACK: KD
|
151
|
-
# #
|
152
|
-
# # When one uploads a file with pos > 0 and 'content-length' != File.size - pos
|
153
|
-
# # then the next request through this connection fails with 400 or 505...
|
154
|
-
# # It seems that it expects the file to be read until EOF.
|
155
|
-
# #
|
156
|
-
# # KIlling the current connection seems to help but it is not good...
|
157
|
-
# #
|
158
|
-
# if @data[:request][:instance].body_stream #&& !@data[:request][:instance].body_stream.eof
|
159
|
-
# pp @data[:request][:instance].body_stream.pos
|
160
|
-
# log "closing current connection because of an issue when an IO object is not read until EOF"
|
161
|
-
# @connection.finish
|
162
|
-
# end
|
163
|
-
end
|
164
|
-
|
165
|
-
def log(message)
|
166
|
-
@data[:options][:cloud_api_logger].log(message, :connection_proxy)
|
167
|
-
end
|
168
|
-
|
169
|
-
#----------------------------
|
170
|
-
# HTTP Connections handling
|
171
|
-
#----------------------------
|
172
|
-
|
173
|
-
def storage # :nodoc:
|
174
|
-
@@storage[Utils::current_thread_and_fiber] ||= {}
|
175
|
-
end
|
176
|
-
|
177
|
-
def current_endpoint # :nodoc:
|
178
|
-
"#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
|
179
|
-
end
|
180
|
-
|
181
|
-
def close_connection(endpoint, reason='') # :nodoc:
|
182
|
-
return nil unless storage[endpoint]
|
183
|
-
|
184
|
-
log "Destroying RightHttpConnection to #{endpoint}, reason: #{reason}"
|
185
|
-
storage[endpoint][:connection].finish(reason)
|
186
|
-
rescue => e
|
187
|
-
log "Exception in close_connection: #{e.class.name}: #{e.message}"
|
188
|
-
ensure
|
189
|
-
storage.delete(endpoint) if endpoint
|
190
|
-
end
|
191
|
-
|
192
|
-
INACTIVE_LIFETIME_LIMIT = 900 # seconds
|
193
|
-
|
194
|
-
# Delete out-of-dated connections for current Thread/Fiber
|
195
|
-
def clean_outdated_connections
|
196
|
-
life_time_scratch = Time::now - INACTIVE_LIFETIME_LIMIT
|
197
|
-
storage.each do |endpoint, connection|
|
198
|
-
if connection[:last_used_at] < life_time_scratch
|
199
|
-
close_connection(endpoint, 'out-of-date')
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
# Expire the connection if it has expired.
|
205
|
-
def current_connection # :nodoc:
|
206
|
-
# Remove dead threads/fibers from the storage
|
207
|
-
self.class::clean_storage
|
208
|
-
# Delete out-of-dated connections
|
209
|
-
clean_outdated_connections
|
210
|
-
# Get current_connection
|
211
|
-
endpoint = current_endpoint
|
212
|
-
unless storage[endpoint]
|
213
|
-
storage[endpoint] = {}
|
214
|
-
storage[endpoint][:connection] = Rightscale::HttpConnection.new( :exception => CloudError,
|
215
|
-
:logger => @data[:options][:cloud_api_logger].logger )
|
216
|
-
log "Creating RightHttpConection to #{endpoint.inspect}"
|
217
|
-
else
|
218
|
-
log "Reusing RightHttpConection to #{endpoint.inspect}"
|
219
|
-
end
|
220
|
-
storage[endpoint][:last_used_at] = Time::now
|
221
|
-
storage[endpoint][:connection]
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|