em_aws 0.2.4 → 0.2.5
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.
- data/Gemfile +2 -1
- data/Gemfile.lock +18 -16
- data/HISTORY.md +11 -0
- data/lib/aws/core/http/em_http_handler.rb +14 -28
- data/lib/em_aws/version.rb +1 -1
- data/spec/em_http_handler_spec.rb +74 -28
- data/spec/spec_helper.rb +3 -6
- metadata +3 -2
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -9,15 +9,15 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: http://rubygems.org/
|
11
11
|
specs:
|
12
|
-
ZenTest (4.8.
|
13
|
-
addressable (2.3.
|
14
|
-
aws-sdk (1.8.1
|
12
|
+
ZenTest (4.8.4)
|
13
|
+
addressable (2.3.3)
|
14
|
+
aws-sdk (1.8.3.1)
|
15
15
|
json (~> 1.4)
|
16
16
|
nokogiri (>= 1.4.4)
|
17
17
|
uuidtools (~> 2.1)
|
18
|
-
builder (3.
|
18
|
+
builder (3.2.0)
|
19
19
|
cookiejar (0.3.0)
|
20
|
-
diff-lcs (1.1
|
20
|
+
diff-lcs (1.2.1)
|
21
21
|
em-http-request (1.0.3)
|
22
22
|
addressable (>= 2.2.3)
|
23
23
|
cookiejar
|
@@ -30,20 +30,21 @@ GEM
|
|
30
30
|
eventmachine (>= 1.0.0.beta.1)
|
31
31
|
eventmachine (1.0.0)
|
32
32
|
eventmachine (1.0.0-java)
|
33
|
+
eventmachine_httpserver (0.2.1)
|
33
34
|
http_parser.rb (0.5.3)
|
34
35
|
http_parser.rb (0.5.3-java)
|
35
|
-
json (1.7.
|
36
|
-
json (1.7.
|
36
|
+
json (1.7.7)
|
37
|
+
json (1.7.7-java)
|
37
38
|
nokogiri (1.5.6)
|
38
39
|
nokogiri (1.5.6-java)
|
39
|
-
rspec (2.
|
40
|
-
rspec-core (~> 2.
|
41
|
-
rspec-expectations (~> 2.
|
42
|
-
rspec-mocks (~> 2.
|
43
|
-
rspec-core (2.
|
44
|
-
rspec-expectations (2.
|
45
|
-
diff-lcs (
|
46
|
-
rspec-mocks (2.
|
40
|
+
rspec (2.13.0)
|
41
|
+
rspec-core (~> 2.13.0)
|
42
|
+
rspec-expectations (~> 2.13.0)
|
43
|
+
rspec-mocks (~> 2.13.0)
|
44
|
+
rspec-core (2.13.0)
|
45
|
+
rspec-expectations (2.13.0)
|
46
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
47
|
+
rspec-mocks (2.13.0)
|
47
48
|
uuidtools (2.1.3)
|
48
49
|
|
49
50
|
PLATFORMS
|
@@ -51,7 +52,8 @@ PLATFORMS
|
|
51
52
|
ruby
|
52
53
|
|
53
54
|
DEPENDENCIES
|
54
|
-
ZenTest (
|
55
|
+
ZenTest (~> 4.8.2)
|
55
56
|
builder
|
56
57
|
em_aws!
|
58
|
+
eventmachine_httpserver
|
57
59
|
rspec
|
data/HISTORY.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
EmAws Changelog
|
2
|
+
=====================
|
3
|
+
|
4
|
+
HEAD
|
5
|
+
=======
|
6
|
+
|
7
|
+
0.2.5
|
8
|
+
=======
|
9
|
+
|
10
|
+
- For non-pooled request set em-http-request inactivity_timeout from aws request.read_timeout object. Remove retries based on status 0 [joshmckin, michalf, #13]
|
11
|
+
- Fetch port from request object [michalf, #13]
|
@@ -33,7 +33,6 @@ module AWS
|
|
33
33
|
]
|
34
34
|
# @return [Hash] The default options to send to EM-Synchrony on each request.
|
35
35
|
attr_reader :default_request_options
|
36
|
-
attr_accessor :status_0_retries
|
37
36
|
|
38
37
|
# Constructs a new HTTP handler using EM-Synchrony.
|
39
38
|
# @param [Hash] options Default options to send to EM-Synchrony on
|
@@ -46,7 +45,6 @@ module AWS
|
|
46
45
|
def initialize options = {}
|
47
46
|
@default_request_options = options
|
48
47
|
@pool = EMConnectionPool.new(options) if options[:pool_size].to_i > 0
|
49
|
-
@status_0_retries = 2 # set to 0 for no retries
|
50
48
|
end
|
51
49
|
|
52
50
|
def handle(request,response,&read_block)
|
@@ -86,13 +84,7 @@ module AWS
|
|
86
84
|
private
|
87
85
|
|
88
86
|
def fetch_url(request)
|
89
|
-
|
90
|
-
if request.use_ssl?
|
91
|
-
url = "https://#{request.host}:443"
|
92
|
-
else
|
93
|
-
url = "http://#{request.host}"
|
94
|
-
end
|
95
|
-
url
|
87
|
+
"#{(request.use_ssl? ? "https" : "http")}://#{request.host}:#{request.port}"
|
96
88
|
end
|
97
89
|
|
98
90
|
def fetch_headers(request)
|
@@ -135,7 +127,9 @@ module AWS
|
|
135
127
|
opts
|
136
128
|
end
|
137
129
|
|
138
|
-
def fetch_response(
|
130
|
+
def fetch_response(request,opts={},&read_block)
|
131
|
+
method = "a#{request.http_method}".downcase.to_sym # aget, apost, aput, adelete, ahead
|
132
|
+
url = fetch_url(request)
|
139
133
|
if @pool
|
140
134
|
@pool.run(url) do |connection|
|
141
135
|
req = connection.send(method, {:keepalive => true}.merge(opts))
|
@@ -143,7 +137,8 @@ module AWS
|
|
143
137
|
return EM::Synchrony.sync req unless opts[:async]
|
144
138
|
end
|
145
139
|
else
|
146
|
-
req = EM::HttpRequest.new(url
|
140
|
+
req = EM::HttpRequest.new(url,
|
141
|
+
:inactivity_timeout => request.read_timeout).send(method,opts)
|
147
142
|
req.stream &read_block if block_given?
|
148
143
|
return EM::Synchrony.sync req unless opts[:async]
|
149
144
|
end
|
@@ -167,28 +162,19 @@ module AWS
|
|
167
162
|
end
|
168
163
|
|
169
164
|
# Builds and attempts the request. Occasionally under load em-http-request
|
170
|
-
# returns a status of 0
|
171
|
-
#
|
172
|
-
#
|
173
|
-
def process_request(request,response,async=false
|
174
|
-
method = "a#{request.http_method}".downcase.to_sym # aget, apost, aput, adelete, ahead
|
165
|
+
# em-http-request returns a status of 0 for various http timeouts, see:
|
166
|
+
# https://github.com/igrigorik/em-http-request/issues/76
|
167
|
+
# https://github.com/eventmachine/eventmachine/issues/175
|
168
|
+
def process_request(request,response,async=false,&read_block)
|
175
169
|
opts = fetch_request_options(request)
|
176
170
|
opts[:async] = (async || opts[:async])
|
177
|
-
url = fetch_url(request)
|
178
171
|
begin
|
179
|
-
http_response = fetch_response(
|
172
|
+
http_response = fetch_response(request,opts,&read_block)
|
180
173
|
unless opts[:async]
|
181
174
|
response.status = http_response.response_header.status.to_i
|
182
|
-
if response.status == 0
|
183
|
-
|
184
|
-
|
185
|
-
else
|
186
|
-
response.network_error = true
|
187
|
-
end
|
188
|
-
else
|
189
|
-
response.headers = fetch_response_headers(http_response)
|
190
|
-
response.body = http_response.response
|
191
|
-
end
|
175
|
+
raise Timeout::Error if response.status == 0
|
176
|
+
response.headers = fetch_response_headers(http_response)
|
177
|
+
response.body = http_response.response
|
192
178
|
end
|
193
179
|
rescue Timeout::Error => error
|
194
180
|
response.network_error = error
|
data/lib/em_aws/version.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
# language governing permissions and limitations under the License.
|
13
13
|
|
14
14
|
require 'spec_helper'
|
15
|
+
require 'eventmachine'
|
16
|
+
require 'evma_httpserver'
|
15
17
|
module AWS::Core
|
16
18
|
module Http
|
17
19
|
class EMFooIO
|
@@ -19,8 +21,25 @@ module AWS::Core
|
|
19
21
|
"/my_path/test.text"
|
20
22
|
end
|
21
23
|
end
|
24
|
+
|
25
|
+
# A slow server for testing timeout,
|
26
|
+
# borrowed from: http://www.igvita.com/2008/05/27/ruby-eventmachine-the-speed-demon/
|
27
|
+
class SlowServer < EventMachine::Connection
|
28
|
+
include EventMachine::HttpServer
|
29
|
+
|
30
|
+
def process_http_request
|
31
|
+
resp = EventMachine::DelegatedHttpResponse.new( self )
|
32
|
+
|
33
|
+
sleep 2 # Simulate a long running request
|
34
|
+
|
35
|
+
resp.status = 200
|
36
|
+
resp.content = "Hello World!"
|
37
|
+
resp.send_response
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
22
41
|
describe EMHttpHandler do
|
23
|
-
|
42
|
+
|
24
43
|
let(:handler) { EMHttpHandler.new(default_request_options) }
|
25
44
|
|
26
45
|
let(:default_request_options) { {} }
|
@@ -40,16 +59,16 @@ module AWS::Core
|
|
40
59
|
EMHttpHandler.should_receive(:fetch_response).with do |url, method,opts|
|
41
60
|
options = opts
|
42
61
|
double("http response",
|
43
|
-
|
44
|
-
|
45
|
-
|
62
|
+
:response => "<foo/>",
|
63
|
+
:code => 200,
|
64
|
+
:to_hash => {})
|
46
65
|
end
|
47
66
|
handler.handle(req, resp)
|
48
67
|
options
|
49
68
|
end
|
50
|
-
|
69
|
+
|
51
70
|
it 'should be accessible from AWS as well as AWS::Core' do
|
52
|
-
AWS::Http::EMHttpHandler.new.should
|
71
|
+
AWS::Http::EMHttpHandler.new.should
|
53
72
|
be_an(AWS::Core::Http::EMHttpHandler)
|
54
73
|
end
|
55
74
|
|
@@ -80,7 +99,7 @@ module AWS::Core
|
|
80
99
|
context 'default request options' do
|
81
100
|
before(:each) do
|
82
101
|
handler.stub(:default_request_options).and_return({ :foo => "BAR",
|
83
|
-
|
102
|
+
:private_key_file => "blarg" })
|
84
103
|
end
|
85
104
|
|
86
105
|
it 'passes extra options through to synchrony' do
|
@@ -90,32 +109,20 @@ module AWS::Core
|
|
90
109
|
it 'uses the default when the request option is not set' do
|
91
110
|
#puts handler.default_request_options
|
92
111
|
handler.default_request_options[:private_key_file].should == "blarg"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
describe '#process_request' do
|
97
|
-
context 'too many retries' do
|
98
|
-
it "should have network error" do
|
99
|
-
EM.synchrony do
|
100
|
-
resp.stub(:status).and_return(0)
|
101
|
-
handler.send(:process_request,(req),(resp),false,3)
|
102
|
-
resp.network_error?.should be_true
|
103
|
-
EM.stop
|
104
|
-
end
|
105
112
|
end
|
106
113
|
end
|
107
114
|
end
|
115
|
+
|
108
116
|
describe '#fetch_request_options' do
|
109
|
-
|
110
117
|
it "should set :query and :body to request.querystring" do
|
111
118
|
opts = handler.send(:fetch_request_options,(req))
|
112
119
|
opts[:query].should eql(req.querystring)
|
113
120
|
end
|
114
|
-
|
121
|
+
|
115
122
|
it "should set :path to request.path" do
|
116
123
|
opts = handler.send(:fetch_request_options,(req))
|
117
124
|
opts[:path].should eql(req.path)
|
118
|
-
end
|
125
|
+
end
|
119
126
|
context "request.body_stream is a StringIO" do
|
120
127
|
it "should set :body to request.body_stream" do
|
121
128
|
opts = handler.send(:fetch_request_options,(req))
|
@@ -139,7 +146,7 @@ module AWS::Core
|
|
139
146
|
handler.send(:fetch_proxy,(req))[:proxy][:port].should == 443
|
140
147
|
end
|
141
148
|
end
|
142
|
-
|
149
|
+
|
143
150
|
describe '#fetch_ssl' do
|
144
151
|
it 'prefers the request option when set' do
|
145
152
|
req.use_ssl = true
|
@@ -148,7 +155,7 @@ module AWS::Core
|
|
148
155
|
handler.send(:fetch_ssl,(req))[:private_key_file].should == "something"
|
149
156
|
handler.send(:fetch_ssl,(req))[:cert_chain_file].should == "something"
|
150
157
|
end
|
151
|
-
|
158
|
+
|
152
159
|
context 'CA cert path' do
|
153
160
|
context 'use_ssl? is true' do
|
154
161
|
|
@@ -164,7 +171,7 @@ module AWS::Core
|
|
164
171
|
it 'should use the ssl_ca_file attribute of the request' do
|
165
172
|
handler.send(:fetch_ssl,(req))[:private_key_file].should == "foobar.txt"
|
166
173
|
end
|
167
|
-
|
174
|
+
|
168
175
|
it 'should use the ssl_ca_file attribute of the request' do
|
169
176
|
handler.send(:fetch_ssl,(req))[:cert_chain_file].should == "foobar.txt"
|
170
177
|
end
|
@@ -179,8 +186,47 @@ module AWS::Core
|
|
179
186
|
handler.send(:fetch_ssl,(req)).should_not include(:private_key_file)
|
180
187
|
end
|
181
188
|
end
|
182
|
-
end
|
183
|
-
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should not timeout" do
|
193
|
+
EM.synchrony {
|
194
|
+
response = Http::Response.new
|
195
|
+
request = Http::Request.new
|
196
|
+
request.host = "127.0.0.1"
|
197
|
+
request.port = "8081"
|
198
|
+
request.uri = "/"
|
199
|
+
request.body_stream = StringIO.new("myStringIO")
|
200
|
+
# turn on our test server
|
201
|
+
EventMachine::run {
|
202
|
+
EventMachine::start_server request.host, request.port, SlowServer
|
203
|
+
}
|
204
|
+
handler.stub(:fetch_url).and_return("http://127.0.0.1:8081")
|
205
|
+
handler.handle(request,response)
|
206
|
+
response.network_error.should be_nil
|
207
|
+
EM.stop
|
208
|
+
}
|
209
|
+
end
|
210
|
+
it "should timeout after 0.1 seconds" do
|
211
|
+
EM.synchrony {
|
212
|
+
response = Http::Response.new
|
213
|
+
request = Http::Request.new
|
214
|
+
request.host = "127.0.0.1"
|
215
|
+
request.port = "8081"
|
216
|
+
request.uri = "/"
|
217
|
+
request.body_stream = StringIO.new("myStringIO")
|
218
|
+
# turn on our test server
|
219
|
+
EventMachine::run {
|
220
|
+
EventMachine::start_server request.host, request.port, SlowServer
|
221
|
+
}
|
222
|
+
handler.stub(:fetch_url).and_return("http://127.0.0.1:8081")
|
223
|
+
request.stub(:read_timeout).and_return(0.01)
|
224
|
+
handler.stub(:connect_timeout).and_return(1) #just to speed up the test
|
225
|
+
handler.handle(request,response)
|
226
|
+
response.network_error.should be_a(Timeout::Error)
|
227
|
+
EM.stop
|
228
|
+
}
|
229
|
+
end
|
184
230
|
end
|
185
231
|
end
|
186
|
-
end
|
232
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,8 +5,7 @@ require 'aws/core/http/em_http_handler'
|
|
5
5
|
require 'rspec'
|
6
6
|
require 'bundler/setup'
|
7
7
|
require 'logger'
|
8
|
-
|
9
|
-
|
8
|
+
require 'em-http'
|
10
9
|
|
11
10
|
# Requires supporting files with custom matchers and macros, etc,
|
12
11
|
# in ./support/ and its subdirectories.
|
@@ -17,8 +16,6 @@ class StubLogger
|
|
17
16
|
end
|
18
17
|
end
|
19
18
|
AWS.config(:logger => StubLogger.new)
|
20
|
-
RSpec.configure do |config|
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
19
|
|
20
|
+
RSpec.configure do |config|
|
21
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em_aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-03-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- .rspec
|
103
103
|
- Gemfile
|
104
104
|
- Gemfile.lock
|
105
|
+
- HISTORY.md
|
105
106
|
- LICENSE.txt
|
106
107
|
- README.md
|
107
108
|
- Rakefile
|