rack-reverse-proxy 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README +26 -0
- data/README.rdoc +38 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/lib/rack/reverse_proxy.rb +85 -0
- data/rack-reverse-proxy.gemspec +58 -0
- data/test/helper.rb +10 -0
- data/test/test_rack-reverse-proxy.rb +4 -0
- metadata +87 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jon Swope
|
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.
|
data/README
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
A Reverse Proxy for Rack
|
2
|
+
|
3
|
+
This is a simple reverse proxy for Rack that pretty heavily rips off Rack Forwarder. It is not meant for production systems (although it may work), as the webserver fronting your app is generally much better at this sort of thing.
|
4
|
+
|
5
|
+
Matchers can be a regex or a string. If a regex is used, you can use the subcaptures in your forwarding url by denoting them with a $.
|
6
|
+
|
7
|
+
Right now if more than one matcher matches any given route, it throws an exception for an ambiguous match. This will probably change later. If no match is found, the call is forwarded to your application.
|
8
|
+
|
9
|
+
Below is an example for configuring the middleware:
|
10
|
+
|
11
|
+
require 'lib/rack/reverse_proxy'
|
12
|
+
|
13
|
+
use Rack::ReverseProxy do
|
14
|
+
# Forward the path /test* to http://example.com/test*
|
15
|
+
reverse_proxy '/test', 'http://example.com/'
|
16
|
+
|
17
|
+
# Forward the path /foo/* to http://example.com/bar/*
|
18
|
+
reverse_proxy /^\/foo(\/.*)$/, 'http://example.com/bar$1'
|
19
|
+
end
|
20
|
+
|
21
|
+
app = proc do |env|
|
22
|
+
[ 200, {'Content-Type' => 'text/plain'}, "b" ]
|
23
|
+
end
|
24
|
+
run app
|
25
|
+
|
26
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= A Reverse Proxy for Rack
|
2
|
+
|
3
|
+
This is a simple reverse proxy for Rack that pretty heavily rips off Rack Forwarder. It is not meant for production systems (although it may work), as the webserver fronting your app is generally much better at this sort of thing.
|
4
|
+
|
5
|
+
Matchers can be a regex or a string. If a regex is used, you can use the subcaptures in your forwarding url by denoting them with a $.
|
6
|
+
|
7
|
+
Right now if more than one matcher matches any given route, it throws an exception for an ambiguous match. This will probably change later. If no match is found, the call is forwarded to your application.
|
8
|
+
|
9
|
+
Below is an example for configuring the middleware:
|
10
|
+
|
11
|
+
require 'lib/rack/reverse_proxy'
|
12
|
+
|
13
|
+
use Rack::ReverseProxy do
|
14
|
+
# Forward the path /test* to http://example.com/test*
|
15
|
+
reverse_proxy '/test', 'http://example.com/'
|
16
|
+
|
17
|
+
# Forward the path /foo/* to http://example.com/bar/*
|
18
|
+
reverse_proxy /^\/foo(\/.*)$/, 'http://example.com/bar$1'
|
19
|
+
end
|
20
|
+
|
21
|
+
app = proc do |env|
|
22
|
+
[ 200, {'Content-Type' => 'text/plain'}, "b" ]
|
23
|
+
end
|
24
|
+
run app
|
25
|
+
|
26
|
+
== Note on Patches/Pull Requests
|
27
|
+
|
28
|
+
* Fork the project.
|
29
|
+
* Make your feature addition or bug fix.
|
30
|
+
* Add tests for it. This is important so I don't break it in a
|
31
|
+
future version unintentionally.
|
32
|
+
* Commit, do not mess with rakefile, version, or history.
|
33
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
34
|
+
* Send me a pull request. Bonus points for topic branches.
|
35
|
+
|
36
|
+
== Copyright
|
37
|
+
|
38
|
+
Copyright (c) 2010 Jon Swope. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rack-reverse-proxy"
|
8
|
+
gem.summary = %Q{A Simple Reverse Proxy for Rack}
|
9
|
+
gem.description = %Q{A Rack based reverse proxy for basic needs. Useful for testing or in cases where webserver configuration is unavailable.}
|
10
|
+
gem.email = "jaswope@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/jaswope/rack-reverse-proxy"
|
12
|
+
gem.authors = ["Jon Swope"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
gem.add_dependency "rack", ">= 1.0.0"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/test_*.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rcov/rcovtask'
|
31
|
+
Rcov::RcovTask.new do |test|
|
32
|
+
test.libs << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
rescue LoadError
|
37
|
+
task :rcov do
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :test => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rake/rdoctask'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "rack-reverse-proxy #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class ReverseProxy
|
5
|
+
def initialize(app = nil, &b)
|
6
|
+
@app = app || lambda { [404, [], []] }
|
7
|
+
@paths = {}
|
8
|
+
instance_eval &b if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
rackreq = Rack::Request.new(env)
|
13
|
+
matcher, url = get_matcher_and_url rackreq.fullpath
|
14
|
+
return @app.call(env) if matcher.nil?
|
15
|
+
|
16
|
+
path = rackreq.fullpath
|
17
|
+
match = case matcher
|
18
|
+
when String
|
19
|
+
path.match(/^#{matcher}/)
|
20
|
+
when Regexp
|
21
|
+
path.match(matcher)
|
22
|
+
end
|
23
|
+
uri = case url
|
24
|
+
when /\$\d/
|
25
|
+
match.to_a.each_with_index { |m, i| url.gsub!("$#{i.to_s}", m) }
|
26
|
+
URI(url)
|
27
|
+
else
|
28
|
+
URI.join(url, path)
|
29
|
+
end
|
30
|
+
|
31
|
+
headers = Rack::Utils::HeaderHash.new
|
32
|
+
env.each { |key, value|
|
33
|
+
if key =~ /HTTP_(.*)/
|
34
|
+
headers[$1] = value
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
res = Net::HTTP.start(uri.host, uri.port) { |http|
|
39
|
+
m = rackreq.request_method
|
40
|
+
case m
|
41
|
+
when "GET", "HEAD", "DELETE", "OPTIONS", "TRACE"
|
42
|
+
req = Net::HTTP.const_get(m.capitalize).new(uri.path, headers)
|
43
|
+
when "PUT", "POST"
|
44
|
+
req = Net::HTTP.const_get(m.capitalize).new(uri.path, headers)
|
45
|
+
req.body_stream = rackreq.body
|
46
|
+
else
|
47
|
+
raise "method not supported: #{method}"
|
48
|
+
end
|
49
|
+
|
50
|
+
http.request(req)
|
51
|
+
}
|
52
|
+
|
53
|
+
[res.code, Rack::Utils::HeaderHash.new(res.to_hash), [res.body]]
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def get_matcher_and_url path
|
59
|
+
matches = @paths.select do |matcher, url|
|
60
|
+
case matcher
|
61
|
+
when String
|
62
|
+
path =~ /^#{matcher}/
|
63
|
+
when Regexp
|
64
|
+
path =~ matcher
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if matches.length < 1
|
69
|
+
nil
|
70
|
+
elsif matches.length > 1
|
71
|
+
raise AmbiguousProxyMatch
|
72
|
+
else
|
73
|
+
matches.first.map{|a| a.dup}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def reverse_proxy matcher, url
|
78
|
+
@paths.merge!(matcher => url)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class AmbiguousProxyMatch < Exception
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rack-reverse-proxy}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Jon Swope"]
|
12
|
+
s.date = %q{2010-04-10}
|
13
|
+
s.description = %q{A Rack based reverse proxy for basic needs. Useful for testing or in cases where webserver configuration is unavailable.}
|
14
|
+
s.email = %q{jaswope@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".gitignore",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/rack/reverse_proxy.rb",
|
28
|
+
"rack-reverse-proxy.gemspec",
|
29
|
+
"test/helper.rb",
|
30
|
+
"test/test_rack-reverse-proxy.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/jaswope/rack-reverse-proxy}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.5}
|
36
|
+
s.summary = %q{A Simple Reverse Proxy for Rack}
|
37
|
+
s.test_files = [
|
38
|
+
"test/helper.rb",
|
39
|
+
"test/test_rack-reverse-proxy.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
48
|
+
s.add_runtime_dependency(%q<rack>, [">= 1.0.0"])
|
49
|
+
else
|
50
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
51
|
+
s.add_dependency(%q<rack>, [">= 1.0.0"])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
55
|
+
s.add_dependency(%q<rack>, [">= 1.0.0"])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-reverse-proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Swope
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-04-10 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: thoughtbot-shoulda
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
version:
|
35
|
+
description: A Rack based reverse proxy for basic needs. Useful for testing or in cases where webserver configuration is unavailable.
|
36
|
+
email: jaswope@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README
|
44
|
+
- README.rdoc
|
45
|
+
files:
|
46
|
+
- .document
|
47
|
+
- .gitignore
|
48
|
+
- LICENSE
|
49
|
+
- README.rdoc
|
50
|
+
- Rakefile
|
51
|
+
- VERSION
|
52
|
+
- lib/rack/reverse_proxy.rb
|
53
|
+
- rack-reverse-proxy.gemspec
|
54
|
+
- test/helper.rb
|
55
|
+
- test/test_rack-reverse-proxy.rb
|
56
|
+
- README
|
57
|
+
has_rdoc: true
|
58
|
+
homepage: http://github.com/jaswope/rack-reverse-proxy
|
59
|
+
licenses: []
|
60
|
+
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options:
|
63
|
+
- --charset=UTF-8
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.3.5
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: A Simple Reverse Proxy for Rack
|
85
|
+
test_files:
|
86
|
+
- test/helper.rb
|
87
|
+
- test/test_rack-reverse-proxy.rb
|