kastner-rack_gateway 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ Author: Erik Kastner
2
+ Copyright (c) 2009.
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
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ = Rack::Gateway
2
+
3
+ A Rack middleware for Failover Proxying.
@@ -0,0 +1,97 @@
1
+ # Rakefile for Rack::Gateway. -*-ruby-*-
2
+ require 'rake/rdoctask'
3
+ require 'rake/testtask'
4
+
5
+ desc "Run all the tests"
6
+ task :default => [:test]
7
+
8
+ desc "Generate RDox"
9
+ task "RDOX" do
10
+ sh "specrb -Ilib:test -a --rdox >RDOX"
11
+ end
12
+
13
+ desc "Run specs with test/unit style output"
14
+ task :test do
15
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
16
+ end
17
+
18
+ desc "Run specs with specdoc style output"
19
+ task :spec do
20
+ sh "specrb -Ilib:test -s -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
21
+ end
22
+
23
+ desc "Run all the tests"
24
+ task :fulltest do
25
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
26
+ end
27
+
28
+ desc "Generate RDoc documentation"
29
+ Rake::RDocTask.new(:rdoc) do |rdoc|
30
+ rdoc.options << '--line-numbers' << '--inline-source' <<
31
+ '--main' << 'README' <<
32
+ '--title' << 'Rack Gateway Documentation' <<
33
+ '--charset' << 'utf-8'
34
+ rdoc.rdoc_dir = "doc"
35
+ rdoc.rdoc_files.include 'README.rdoc'
36
+ rdoc.rdoc_files.include 'RDOX'
37
+ rdoc.rdoc_files.include('lib/rack/*.rb')
38
+ rdoc.rdoc_files.include('lib/rack/*/*.rb')
39
+ end
40
+ task :rdoc => ["RDOX"]
41
+
42
+
43
+ # PACKAGING =================================================================
44
+
45
+ # load gemspec like github's gem builder to surface any SAFE issues.
46
+ require 'rubygems/specification'
47
+ $spec = eval(File.read('rack_gateway.gemspec'))
48
+
49
+ def package(ext='')
50
+ "pkg/rack_gateway-#{$spec.version}" + ext
51
+ end
52
+
53
+ desc 'Build packages'
54
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
55
+
56
+ desc 'Build and install as local gem'
57
+ task :install => package('.gem') do
58
+ sh "gem install #{package('.gem')}"
59
+ end
60
+
61
+ directory 'pkg/'
62
+
63
+ file package('.gem') => %w[pkg/ rack_gateway.gemspec] + $spec.files do |f|
64
+ sh "gem build rack_gateway.gemspec"
65
+ mv File.basename(f.name), f.name
66
+ end
67
+
68
+ file package('.tar.gz') => %w[pkg/] + $spec.files do |f|
69
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
70
+ end
71
+
72
+ # desc 'Publish gem and tarball to rubyforge'
73
+ # task 'publish:gem' => [package('.gem'), package('.tar.gz')] do |t|
74
+ # sh <<-end
75
+ # rubyforge add_release rack rack_gateway #{$spec.version} #{package('.gem')} &&
76
+ # rubyforge add_file rack rack_gateway #{$spec.version} #{package('.tar.gz')}
77
+ # end
78
+ # end
79
+
80
+ # GEMSPEC ===================================================================
81
+
82
+ file 'rack_gateway.gemspec' => FileList['{lib,test}/**','Rakefile', 'README.rdoc'] do |f|
83
+ # read spec file and split out manifest section
84
+ spec = File.read(f.name)
85
+ parts = spec.split(" # = MANIFEST =\n")
86
+ fail 'bad spec' if parts.length != 3
87
+ # determine file list from git ls-files
88
+ files = `git ls-files`.
89
+ split("\n").sort.reject{ |file| file =~ /^\./ }.
90
+ map{ |file| " #{file}" }.join("\n")
91
+ # piece file back together and write...
92
+ parts[1] = " s.files = %w[\n#{files}\n ]\n"
93
+ spec = parts.join(" # = MANIFEST =\n")
94
+ spec.sub!(/s.date = '.*'/, "s.date = '#{Time.now.strftime("%Y-%m-%d")}'")
95
+ File.open(f.name, 'w') { |io| io.write(spec) }
96
+ puts "updated #{f.name}"
97
+ end
@@ -0,0 +1,60 @@
1
+ require 'curb'
2
+
3
+ module Rack
4
+ class Gateway
5
+ attr_accessor :env
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ self.dup._call(env)
13
+ end
14
+
15
+ def upstream_url
16
+ # raise env.inspect
17
+ "%s://%s%s%s" % [
18
+ @env["rack.url_scheme"],
19
+ ENV["upstream_server"],
20
+ @env["PATH_INFO"],
21
+ @env["QUERY_STRING"].empty? ? "" : "?#{@env["QUERY_STRING"]}"
22
+ ]
23
+ end
24
+
25
+ def request_headers
26
+ headers = @env.select {|k,v| k.match(/^HTTP_/)}.map do |key, value|
27
+ my_key = key.gsub(/^HTTP_/, '').gsub(/_/, '-').downcase.capitalize
28
+ [my_key, value]
29
+ end
30
+ headers = Hash[*headers.flatten]
31
+ end
32
+
33
+ def response_headers(curl)
34
+ headers = curl.header_str.split("\r\n")[1..-1].map{|h| h.split(": ")}
35
+ headers
36
+ Hash[*headers.flatten]
37
+ end
38
+
39
+ def _call(env)
40
+ @env = env
41
+ @status, @headers, @response = @app.call(@env)
42
+
43
+ if @status == 404
44
+ c = Curl::Easy.new(upstream_url)
45
+ c.headers = request_headers
46
+ case @env["REQUEST_METHOD"]
47
+ when /get/i
48
+ c.perform
49
+ when /post/i
50
+ c.http_post(@env["rack.request.form_vars"])
51
+ end
52
+ @response = c.body_str
53
+ @status = c.response_code
54
+ @headers = response_headers(c)
55
+ end
56
+
57
+ [@status, @headers, @response]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,36 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+
5
+ s.name = 'rack_gateway'
6
+ s.version = '0.1'
7
+ s.date = '2009-04-02'
8
+
9
+ s.description = "Rack Gateway Proxy"
10
+ s.summary = "Rack Gateway Proxy"
11
+
12
+ s.authors = ["Erik Kastner"]
13
+ s.email = "kastner@gmail.com"
14
+
15
+ # = MANIFEST =
16
+ s.files = %w[
17
+ Rakefile
18
+ lib/rack_gateway.rb
19
+ rack_gateway.gemspec
20
+ test/spec_rack_gateway.rb
21
+ ]
22
+ # = MANIFEST =
23
+
24
+ s.test_files = s.files.select {|path| path =~ /^test\/spec_.*\.rb/}
25
+
26
+ s.extra_rdoc_files = %w[README.rdoc MIT-LICENSE]
27
+ s.add_dependency 'rack', '~> 0.9.1'
28
+ s.add_dependency 'test-spec', '~> 0.9.0'
29
+ s.add_development_dependency 'json', '>= 1.1'
30
+
31
+ s.has_rdoc = true
32
+ s.homepage = "http://github.com/kastner/rack_gateway/"
33
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "rack-contrib", "--main", "README"]
34
+ s.require_paths = %w[lib]
35
+ s.rubygems_version = '1.1.1'
36
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack_gateway'
4
+
5
+ context 'Rack::Gateway' do
6
+ before(:each) do
7
+ ENV["upstream_server"] = "localhost"
8
+ @test_headers = {'Content-Type' => 'text/html'}
9
+ @test_body = "Not Found"
10
+ @app = lambda { |env| [404, @test_headers, [@test_body]]}
11
+ @gateway = Rack::Gateway.new(@app)
12
+ end
13
+
14
+ specify "request url should be set" do
15
+ request = Rack::MockRequest.env_for("/bob", :lint => true, :fatal => true)
16
+ @gateway.env = request
17
+ @gateway.upstream_url.should.equal "http://localhost/bob"
18
+ end
19
+
20
+ specify "request url should be set even with a query string" do
21
+ request = Rack::MockRequest.env_for("/bob?a=1", :lint => true, :fatal => true)
22
+ @gateway.env = request
23
+ @gateway.upstream_url.should.equal "http://localhost/bob?a=1"
24
+ end
25
+
26
+ specify "forwarding request should pass-through headers" do
27
+ request = Rack::MockRequest.env_for("/bob", {
28
+ :lint => true, :fatal => true,
29
+ "HTTP_ACCEPT" => "application/xml,text/html;q=0.9,*/*;q=0.5",
30
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16"
31
+ })
32
+ @gateway.env = request
33
+ @gateway.request_headers.should.include?("User-agent")
34
+ @gateway.request_headers['User-agent'].should.match /Safari/
35
+ end
36
+
37
+ # specify "A POST should forward the post data" do
38
+ # end
39
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kastner-rack_gateway
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Erik Kastner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-02 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rack
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: test-spec
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: json
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "1.1"
44
+ version:
45
+ description: Rack Gateway Proxy
46
+ email: kastner@gmail.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README.rdoc
53
+ - MIT-LICENSE
54
+ files:
55
+ - Rakefile
56
+ - lib/rack_gateway.rb
57
+ - rack_gateway.gemspec
58
+ - test/spec_rack_gateway.rb
59
+ - README.rdoc
60
+ - MIT-LICENSE
61
+ has_rdoc: true
62
+ homepage: http://github.com/kastner/rack_gateway/
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --line-numbers
66
+ - --inline-source
67
+ - --title
68
+ - rack-contrib
69
+ - --main
70
+ - README
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.2.0
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: Rack Gateway Proxy
92
+ test_files:
93
+ - test/spec_rack_gateway.rb