em_aws 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|