em_aws 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ Gemfile.lock
2
+ pkg/*
3
+ *.gem
4
+ .bundle
5
+ .DS_Store
6
+ nbproject/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in em_aws.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Joshua T. Mckinney
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ ALL AWS-SDK code is covered under the AWS-SDK [license](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/LICENSE.txt)
@@ -0,0 +1,41 @@
1
+ # em_aws
2
+ An EM-Synchrony handler for Ruby [AWS-SDK]
3
+
4
+ ## Installation
5
+
6
+ em_aws is available through [Rubygems](http://rubygems.org/gems/simple_model) and can be installed via:
7
+
8
+ $ gem install em_aws
9
+
10
+ ## Rails 3 setup (no rails 2 sorry)
11
+ Setup AWS-SKD as you would normally. [AWS-SKD](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc)
12
+
13
+ Assuming you've already setup async-rails...
14
+
15
+ In your environments files add:
16
+ require 'aws-sdk'
17
+ require 'aws/core/http/em_http_handler'
18
+ AWS.config(
19
+ :http_handler => AWS::Http::EMHttpHandler.new)
20
+
21
+ Your done.
22
+
23
+ All requests to AWS will use EM-Synchrony's implementation of em-http-request for non-block HTTP request and fiber management.
24
+
25
+ ### References
26
+ [aws-sdk](https://github.com/amazonwebservices/aws-sdk-for-ruby)
27
+ [Async-Rails](https://github.com/igrigorik/async-rails)
28
+ [Phat](http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/)
29
+
30
+ ## Contributing to em_aws
31
+
32
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
33
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
34
+ * Fork the project
35
+ * Start a feature/bugfix branch
36
+ * Commit and push until you are happy with your contribution
37
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
38
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
39
+
40
+ ## Thanks
41
+ Code based on HTTParty Hander in [AWS-SKD](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc)
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "em_aws/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "em_aws"
7
+ s.version = EmAws::VERSION
8
+ s.authors = ["Joshua Mckinney"]
9
+ s.email = ["joshmckin@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Adds EM-Synchrony support to AWS-SDK gem}
12
+ s.description = %q{Adds EM-Synchrony support to AWS-SDK gem}
13
+
14
+ s.rubyforge_project = "em_aws"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_runtime_dependency "aws-sdk"
24
+ s.add_runtime_dependency "em-synchrony"
25
+ s.add_runtime_dependency "em-http-request"
26
+ end
@@ -0,0 +1,142 @@
1
+ # http://docs.amazonwebservices.com/AWSRubySDK/latest/
2
+
3
+ require "em-synchrony"
4
+ require "em-synchrony/em-http"
5
+
6
+ module AWS
7
+ module Core
8
+ module Http
9
+
10
+ # An EM-Synchrony implementation for Fiber based asynchronous ruby application.
11
+ # See https://github.com/igrigorik/async-rails and
12
+ # http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/
13
+ # for examples of Aync-Rails application
14
+ #
15
+ # In Rails add the following to you various environment files:
16
+ #
17
+ # require 'aws-sdk'
18
+ # require 'aws/core/http/em_http_handler'
19
+ # AWS.config(
20
+ # :http_handler => AWS::Http::EMHttpHandler.new(
21
+ # :proxy => {:host => "http://myproxy.com",:port => 80}
22
+ # )
23
+ # )
24
+ #
25
+ class EMHttpHandler
26
+
27
+ # @return [Hash] The default options to send to EM-Synchrony on each
28
+ # request.
29
+ attr_reader :default_request_options
30
+
31
+ # Constructs a new HTTP handler using EM-Synchrony.
32
+ #
33
+ # @param [Hash] options Default options to send to HTTParty on
34
+ # each request. These options will be sent to +get+, +post+,
35
+ # +head+, +put+, or +delete+ when a request is made. Note
36
+ # that +:body+, +:head+, +:parser+, and +:ssl_ca_file+ are
37
+ # ignored. If you need to set the CA file, you should use the
38
+ # +:ssl_ca_file+ option to {AWS.config} or
39
+ # {AWS::Configuration} instead.
40
+ def initialize options = {}
41
+ puts "Using EM-Synchrony for AWS requests"
42
+ @default_request_options = options
43
+ end
44
+
45
+ def fetch_url(request)
46
+ url = nil
47
+ if request.use_ssl?
48
+ url = "https://#{request.host}:443#{request.uri}"
49
+ else
50
+ url = "http://#{request.host}#{request.uri}"
51
+ end
52
+ url
53
+ end
54
+
55
+ def fetch_headers(request)
56
+ # Net::HTTP adds this header for us when the body is
57
+ # provided, but it messes up signing
58
+ headers = { 'content-type' => '' }
59
+
60
+ # headers must have string values (net http calls .strip on them)
61
+ request.headers.each_pair do |key,value|
62
+ headers[key] = value.to_s
63
+ end
64
+
65
+ {:head => headers}
66
+ end
67
+
68
+ def fetch_proxy(request)
69
+ opts={}
70
+ if request.proxy_uri
71
+ opts[:proxy] = {:host => request.proxy_uri.host,:port => request.proxy_uri.port}
72
+ end
73
+ opts
74
+ end
75
+
76
+ def fetch_ssl(request)
77
+ opts = {}
78
+ if request.use_ssl? && request.ssl_verify_peer?
79
+ opts[:private_key_file] = request.ssl_ca_file
80
+ opts[:cert_chain_file]= request.ssl_ca_file
81
+ end
82
+ opts
83
+ end
84
+
85
+ def request_options(request)
86
+ fetch_headers(request).
87
+ merge(fetch_proxy(request)).
88
+ merge(fetch_ssl(request))
89
+ end
90
+
91
+ def fetch_response(url,method,opts={})
92
+ new_response = nil
93
+ if EM::reactor_running?
94
+ #puts "Reactor is running"
95
+ http = EM::HttpRequest.new(url).send(method, opts)
96
+ http.callback { new_response = http}
97
+ http.errback { puts "#{method} to AWS failed." }
98
+ else
99
+ EM.synchrony do
100
+ #puts "WARNING: Had to start EM"
101
+ http = EM::HttpRequest.new(url).send(method, opts)
102
+ http.callback { new_response = http}
103
+ http.errback { puts "#{method} to AWS failed." }
104
+ EM.stop
105
+ end
106
+ end
107
+ new_response
108
+ end
109
+
110
+ def handle(request, response)
111
+ #puts "Using EM!!!!"
112
+ opts = default_request_options.merge({
113
+ :body => request.body
114
+ }).merge(request_options(request))
115
+
116
+ url = fetch_url(request)
117
+
118
+ # get, post, put, delete, head
119
+ method = request.http_method.downcase
120
+
121
+ begin
122
+ http_response = fetch_response(url,method,opts)
123
+ rescue Timeout::Error, Errno::ETIMEDOUT => e
124
+ response.timeout = true
125
+ else
126
+ response.body = http_response.response
127
+ response.status = http_response.response_header.status.to_i
128
+ response.headers = http_response.response_header.to_hash
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ # We move this from AWS::Http to AWS::Core::Http, but we want the
136
+ # previous default handler to remain accessible from its old namesapce
137
+ # @private
138
+ module Http
139
+ class EMHttpHandler < Core::Http::EMHttpHandler; end
140
+ end
141
+
142
+ end
@@ -0,0 +1,23 @@
1
+ require 'aws-sdk'
2
+ require 'em_aws/version'
3
+ require 'em-http'
4
+ require 'em-synchrony'
5
+ require 'em-synchrony/em-http'
6
+ require 'aws/core/autoloader'
7
+
8
+ module AWS
9
+ module Core
10
+ module Http
11
+ AWS.register_autoloads(self) do
12
+ autoload :EMHttpHandler, 'em_http_handler'
13
+ end
14
+ end
15
+ end
16
+
17
+ # the http party handler should still be accessible from its old namespace
18
+ module Http
19
+ AWS.register_autoloads(self, 'aws/core/http') do
20
+ autoload :HTTPartyHandler, 'httparty_handler'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module EmAws
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,161 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ require 'spec_helper'
15
+
16
+ module AWS::Core
17
+ module Http
18
+ describe EMHttpHandler do
19
+
20
+ let(:handler) { EMHttpHandler.new(default_request_options) }
21
+
22
+ let(:default_request_options) { {} }
23
+
24
+ let(:req) do
25
+ r = Http::Request.new
26
+ r.host = "foo.bar.com"
27
+ r
28
+ end
29
+
30
+ let(:resp) { Http::Response.new }
31
+
32
+ let(:em_http_options) do
33
+ options = nil
34
+ EMHttpHandler.should_receive(:fetch_response).with do |url, method,opts|
35
+ puts "here"
36
+ options = opts
37
+ double("http response",
38
+ :response => "<foo/>",
39
+ :code => 200,
40
+ :to_hash => {})
41
+ end
42
+ handler.handle(req, resp)
43
+ options
44
+ end
45
+
46
+ it 'should be accessible from AWS as well as AWS::Core' do
47
+ AWS::Http::EMHttpHandler.new.should
48
+ be_an(AWS::Core::Http::EMHttpHandler)
49
+ end
50
+
51
+ describe '#initialize' do
52
+
53
+ it 'should set the default request options' do
54
+ described_class.new(:foo => "BAR").default_request_options.
55
+ should == { :foo => "BAR" }
56
+ end
57
+
58
+ end
59
+
60
+ describe '#handle' do
61
+
62
+ context 'timeouts' do
63
+
64
+ it 'should rescue Timeout::Error' do
65
+ handler.stub(:fetch_response).
66
+ and_raise(Timeout::Error)
67
+ lambda { handler.handle(req, resp) }.
68
+ should_not raise_error
69
+ end
70
+
71
+ it 'should rescue Errno::ETIMEDOUT' do
72
+ handler.stub(:fetch_response).
73
+ and_raise(Errno::ETIMEDOUT)
74
+ lambda { handler.handle(req, resp) }.
75
+ should_not raise_error
76
+ end
77
+
78
+ it 'should indicate that there was a timeout' do
79
+ handler.stub(:fetch_response).
80
+ and_raise(Errno::ETIMEDOUT)
81
+ handler.handle(req, resp)
82
+ resp.timeout?.should be_true
83
+ end
84
+
85
+ end
86
+
87
+ context 'default request options' do
88
+ before(:each) do
89
+ handler.stub(:default_request_options).and_return({ :foo => "BAR",
90
+ :private_key_file => "blarg" })
91
+ end
92
+
93
+ it 'passes extra options through to synchrony' do
94
+ handler.default_request_options[:foo].should == "BAR"
95
+ end
96
+
97
+ it 'uses the default when the request option is not set' do
98
+ #puts handler.default_request_options
99
+ handler.default_request_options[:private_key_file].should == "blarg"
100
+ end
101
+
102
+ end
103
+
104
+
105
+ describe '#fetch_proxy' do
106
+ context ':proxy_uri' do
107
+
108
+ it 'passes proxy address and port from the request' do
109
+ req.proxy_uri = URI.parse('https://user:pass@proxy.com:443/path?query')
110
+ handler.fetch_proxy(req)[:proxy][:host].should == 'proxy.com'
111
+ handler.fetch_proxy(req)[:proxy][:port].should == 443
112
+ end
113
+
114
+ end
115
+
116
+ describe '#fetch_ssl' do
117
+ it 'prefers the request option when set' do
118
+ req.use_ssl = true
119
+ req.ssl_verify_peer = true
120
+ req.ssl_ca_file = "something"
121
+ handler.fetch_ssl(req)[:private_key_file].should == "something"
122
+ handler.fetch_ssl(req)[:cert_chain_file].should == "something"
123
+ end
124
+
125
+ context 'CA cert path' do
126
+
127
+ context 'use_ssl? is true' do
128
+
129
+ before(:each) { req.use_ssl = true }
130
+
131
+ context 'ssl_verify_peer? is true' do
132
+
133
+ before(:each) do
134
+ req.ssl_verify_peer = true
135
+ req.ssl_ca_file = "foobar.txt"
136
+ end
137
+
138
+ it 'should use the ssl_ca_file attribute of the request' do
139
+ handler.fetch_ssl(req)[:private_key_file].should == "foobar.txt"
140
+ end
141
+
142
+ it 'should use the ssl_ca_file attribute of the request' do
143
+ handler.fetch_ssl(req)[:cert_chain_file].should == "foobar.txt"
144
+ end
145
+ end
146
+
147
+ it 'should not set the ssl_ca_file option without ssl_verify_peer?' do
148
+ handler.fetch_ssl(req).should_not include(:private_key_file)
149
+ end
150
+ end
151
+
152
+ it 'should not set the ssl_ca_file option without use_ssl?' do
153
+ handler.fetch_ssl(req).should_not include(:private_key_file)
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,18 @@
1
+ #$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ #$LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'em_aws'
4
+ require 'rspec'
5
+ require 'bundler/setup'
6
+
7
+
8
+
9
+ # Requires supporting files with custom matchers and macros, etc,
10
+ # in ./support/ and its subdirectories.
11
+ #Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
+
13
+
14
+ RSpec.configure do |config|
15
+
16
+
17
+ end
18
+
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em_aws
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joshua Mckinney
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-16 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70193695301820 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70193695301820
25
+ - !ruby/object:Gem::Dependency
26
+ name: aws-sdk
27
+ requirement: &70193695298840 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70193695298840
36
+ - !ruby/object:Gem::Dependency
37
+ name: em-synchrony
38
+ requirement: &70193695297500 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70193695297500
47
+ - !ruby/object:Gem::Dependency
48
+ name: em-http-request
49
+ requirement: &70193695295460 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70193695295460
58
+ description: Adds EM-Synchrony support to AWS-SDK gem
59
+ email:
60
+ - joshmckin@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - .rspec
67
+ - Gemfile
68
+ - LICENSE.txt
69
+ - README.md
70
+ - Rakefile
71
+ - em_aws.gemspec
72
+ - lib/aws/core/http/em_http_handler.rb
73
+ - lib/em_aws.rb
74
+ - lib/em_aws/version.rb
75
+ - spec/em_http_handler_spec.rb
76
+ - spec/spec_helper.rb
77
+ homepage: ''
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project: em_aws
97
+ rubygems_version: 1.8.6
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Adds EM-Synchrony support to AWS-SDK gem
101
+ test_files:
102
+ - spec/em_http_handler_spec.rb
103
+ - spec/spec_helper.rb