shuber-proxy 1.2.0
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/CHANGELOG +64 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +55 -0
- data/Rakefile +22 -0
- data/init.rb +1 -0
- data/lib/huberry/action_controller/abstract_request.rb +41 -0
- data/lib/huberry/action_controller/base.rb +120 -0
- data/lib/huberry/action_controller/named_route_collection.rb +30 -0
- data/lib/huberry/action_controller/url_rewriter.rb +18 -0
- data/lib/huberry/action_view/url_helper.rb +18 -0
- data/test/abstract_request_test.rb +68 -0
- data/test/base_test.rb +174 -0
- data/test/named_route_collection_test.rb +28 -0
- data/test/url_helper_test.rb +40 -0
- data/test/url_rewriter_test.rb +36 -0
- metadata +70 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
2008-11-14 - Sean Huber (shuber@huberry.com)
|
2
|
+
* Fix bug - "redirect_to some_path" now uses a forwarded host if it exists
|
3
|
+
* Gemify
|
4
|
+
* Update README
|
5
|
+
* Update proxy.gemspec
|
6
|
+
|
7
|
+
2008-10-30 - Sean Huber (shuber@huberry.com)
|
8
|
+
* Update documentation
|
9
|
+
* Move the logic that calculates the session_domain into its own method and update documentation
|
10
|
+
* Update README
|
11
|
+
|
12
|
+
2008-10-27 - Sean Huber (shuber@huberry.com)
|
13
|
+
* rewrite_url also adds the :host option as options is a Hash
|
14
|
+
* Move the logic that calculates the proxy_relative_url_root into its own method
|
15
|
+
|
16
|
+
2008-10-21 - Sean Huber (shuber@huberry.com)
|
17
|
+
* Fix bug - only add the :host option to url_helper if options is a Hash
|
18
|
+
|
19
|
+
2008-10-06 - Sean Huber (shuber@huberry.com)
|
20
|
+
* Add tests to ensure asset helpers work correctly
|
21
|
+
|
22
|
+
2008-10-05 - Sean Huber (shuber@huberry.com)
|
23
|
+
* Add failing named route test
|
24
|
+
* Named routes now work with forwarded hosts
|
25
|
+
* ActionView::Base#url_for uses forwarded hosts correctly
|
26
|
+
* Update README
|
27
|
+
* Update init.rb
|
28
|
+
|
29
|
+
2008-10-03 - Sean Huber (shuber@huberry.com)
|
30
|
+
* Add tests to ensure default host and relative_url_root are restored when an action redirects
|
31
|
+
* Update README
|
32
|
+
* The original session_domain is now restored after each request
|
33
|
+
|
34
|
+
2008-10-02 - Sean Huber (shuber@huberry.com)
|
35
|
+
* Remove Dispatcher and moved that logic into Base
|
36
|
+
* Add Rakefile
|
37
|
+
* Fix bug - referred to ActionController instead of ActionController::Base
|
38
|
+
* Fix bug - plugin was not being loaded properly
|
39
|
+
* Update README
|
40
|
+
* Fix bug - proxy_relative_url_root was not being set on every request
|
41
|
+
* Fix bug - relative_url_root was always being delegated to ActionController::AbstractRequest
|
42
|
+
|
43
|
+
2008-10-01 - Sean Huber (shuber@huberry.com)
|
44
|
+
* Move some forwarded host logic into AbstractRequest
|
45
|
+
* Add AbstractRequest tests and renamed BaseTest file
|
46
|
+
* Add more AbstractRequest tests
|
47
|
+
* ActionController::Base will delegate relative_url_root to AbstractRequest if necessary to support older versions of actionpack
|
48
|
+
* Add more Base tests
|
49
|
+
* Reorder requires and inclusions in proxy.rb
|
50
|
+
* Update CHANGELOG
|
51
|
+
* Update README
|
52
|
+
* Add UrlRewriter
|
53
|
+
* Add more tests
|
54
|
+
|
55
|
+
2008-09-29 - Sean Huber (shuber@huberry.com)
|
56
|
+
* Initial import
|
57
|
+
* Add some tests - still need to figure out how to test Dispatcher
|
58
|
+
* Base automatically detects HTTP_X_FORWARDED_URI and determines relative_url_root (can be overwritten)
|
59
|
+
* Update Base tests
|
60
|
+
* Base can now parse a comma separated string of forwarded uris
|
61
|
+
* The HTTP_X_FORWARDED_URI variable name can be changed to something else
|
62
|
+
* Update README
|
63
|
+
* Regex to determine relative root url is now properly escaped
|
64
|
+
* Fix bug - Base was not setting the class relative_url_root correctly
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Sean Huber (shuber@huberry.com)
|
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.markdown
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
Proxy
|
2
|
+
=====
|
3
|
+
|
4
|
+
A gem/plugin that allows rails applications to dynamically respond to proxied requests by detecting forwarded host/uri headers and setting the session domain, default host, and relative url root. The plugin adds this functionality to calls to url_for, named route helpers, and view url helpers while still allowing you to specifically set the :host and :only\_path options to override this behavior.
|
5
|
+
|
6
|
+
The original session domain, default host, and relative url root will be restored after each request.
|
7
|
+
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
|
12
|
+
script/plugin install git://github.com/shuber/proxy.git
|
13
|
+
OR
|
14
|
+
gem install shuber-proxy --source http://gems.github.com
|
15
|
+
|
16
|
+
|
17
|
+
Usage
|
18
|
+
-----
|
19
|
+
|
20
|
+
Lets say you have a suite of hosted applications all running on the same domain but mounted on different paths. One of them is an order/invoicing application located at:
|
21
|
+
|
22
|
+
http://client.example.com/orders
|
23
|
+
|
24
|
+
Imagine you sold an account to a client but the client wants the application to look like its running on his own domain, so they'll set up a proxy so they can access your application at:
|
25
|
+
|
26
|
+
http://clientdomain.com/orders
|
27
|
+
|
28
|
+
This plugin will automatically detect this forwarded host and set the session domain and default host (for url generation) accordingly.
|
29
|
+
|
30
|
+
Now imagine the client had an existing ordering system already running at /orders, and he wants to slowly migrate his data into your application, so he'll need both applications running for awhile. He wants to keep his original ordering application running at /orders and he wants your application running at:
|
31
|
+
|
32
|
+
http://clientdomain.com/neworders
|
33
|
+
|
34
|
+
All the client has to do is proxy /neworders to http://client.example.com/orders and this plugin will automatically detect the forwarded request uri and set the relative url root for your application accordingly. Now whenever urls are generated, they will correctly use /neworders as the relative url root instead of /orders.
|
35
|
+
|
36
|
+
Note: this plugin looks for a request header called 'HTTP\_X\_FORWARDED_URI' to detect the relative root url by default, but this can be overwritten like so:
|
37
|
+
|
38
|
+
ActionController::AbstractRequest.forwarded_uri_header_name = 'SOME_CUSTOM_HEADER_NAME'
|
39
|
+
|
40
|
+
You can add that line in environment.rb or an initializer.
|
41
|
+
|
42
|
+
|
43
|
+
Relative Url Root Proxy Setup
|
44
|
+
-----------------------------
|
45
|
+
|
46
|
+
The client's proxy must forward the request uri header in order for this plugin to automatically set the relative url root correctly. Here is how the client would setup a proxy in apache for the example above:
|
47
|
+
|
48
|
+
RewriteRule ^neworders(.*) http://client.example.com/orders$1 [P,E=originalUri:%{REQUEST_URI}]
|
49
|
+
RequestHeader append X_FORWARDED_URI %{originalUri}e
|
50
|
+
|
51
|
+
|
52
|
+
Contact
|
53
|
+
-------
|
54
|
+
|
55
|
+
Problems, comments, and suggestions all welcome: [shuber@huberry.com](mailto:shuber@huberry.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run the proxy tests'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the proxy plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the proxy plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Proxy'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README.markdown')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_dependency File.dirname(__FILE__) + '/lib/proxy'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Huberry
|
2
|
+
module ActionController
|
3
|
+
module AbstractRequest
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
mattr_accessor :forwarded_uri_header_name
|
7
|
+
self.forwarded_uri_header_name = 'HTTP_X_FORWARDED_URI'
|
8
|
+
memoize :forwarded_hosts, :forwarded_uris if respond_to? :memoize
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Parses the forwarded host header and returns an array of forwarded hosts
|
13
|
+
#
|
14
|
+
# For example:
|
15
|
+
#
|
16
|
+
# If the HTTP_X_FORWARDED_HOST header was set to
|
17
|
+
# 'some-domain.com, some-other-domain.com, and-another-domain.com'
|
18
|
+
#
|
19
|
+
# This method would return ['some-domain.com', 'some-other-domain.com', 'and-another-domain.com']
|
20
|
+
#
|
21
|
+
# Returns an empty array if there aren't any forwarded hosts
|
22
|
+
def forwarded_hosts
|
23
|
+
env['HTTP_X_FORWARDED_HOST'].to_s.split(/,\s*/)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Parses the forwarded uri header and returns an array of forwarded uris
|
27
|
+
#
|
28
|
+
# For example:
|
29
|
+
#
|
30
|
+
# If the HTTP_X_FORWARDED_URI header was set to
|
31
|
+
# '/some/path, /some/other/path, /and/another/path'
|
32
|
+
#
|
33
|
+
# This method would return ['/some/path, '/some/other/path', '/and/another/path']
|
34
|
+
#
|
35
|
+
# Returns an empty array if there aren't any forwarded uris
|
36
|
+
def forwarded_uris
|
37
|
+
env[self.forwarded_uri_header_name].to_s.split(/,\s*/)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Huberry
|
2
|
+
module ActionController
|
3
|
+
module Base
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
before_filter :set_proxy_relative_url_root
|
7
|
+
around_filter :swap_default_host
|
8
|
+
around_filter :swap_relative_url_root
|
9
|
+
around_filter :swap_session_domain
|
10
|
+
cattr_accessor :original_relative_url_root
|
11
|
+
cattr_accessor :proxy_relative_url_root
|
12
|
+
class << self; delegate :relative_url_root, :relative_url_root=, :to => ::ActionController::AbstractRequest unless ::ActionController::Base.respond_to? :relative_url_root; end
|
13
|
+
alias_method_chain :redirect_to, :proxy
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
# Calculates the <tt>relative_url_root</tt> by parsing the request path out of the
|
20
|
+
# first forwarded uri
|
21
|
+
#
|
22
|
+
# For example:
|
23
|
+
#
|
24
|
+
# http://example.com/manage/videos/new
|
25
|
+
# gets proxied to
|
26
|
+
# http://your-domain.com/videos/new
|
27
|
+
#
|
28
|
+
# The first forwarded uri would be: /manage/videos/new
|
29
|
+
# and the request path would be: /videos/new
|
30
|
+
#
|
31
|
+
# So this method would return: /manage
|
32
|
+
def parse_proxy_relative_url_root
|
33
|
+
request.forwarded_uris.first.gsub(/#{Regexp.escape(request.path)}$/, '')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Calculates the <tt>session_domain</tt> by parsing the first domain.tld out of the
|
37
|
+
# first forwarded host and prepending a '.'
|
38
|
+
#
|
39
|
+
# For example:
|
40
|
+
#
|
41
|
+
# http://example.com/manage/videos/new
|
42
|
+
# http://some.other-domain.com/videos/new
|
43
|
+
# both get proxied to
|
44
|
+
# http://your-domain.com/videos/new
|
45
|
+
#
|
46
|
+
# The resulting session domain for the first url would be: '.example.com'
|
47
|
+
# The resulting session domain for the second url would be: '.other-domain.com'
|
48
|
+
def parse_session_domain
|
49
|
+
".#{$1}" if /([^\.]+\.[^\.]+)$/.match(request.forwarded_hosts.first)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Forces redirects to use the <tt>default_url_options[:host]</tt> if it exists unless a host
|
53
|
+
# is already set
|
54
|
+
#
|
55
|
+
# For example:
|
56
|
+
#
|
57
|
+
# http://example.com
|
58
|
+
# gets proxied to
|
59
|
+
# http://your-domain.com
|
60
|
+
#
|
61
|
+
# If you have an action that calls <tt>redirect_to new_videos_path</tt>, the example.com domain
|
62
|
+
# would be used instead of your-domain.com
|
63
|
+
def redirect_to_with_proxy(*args)
|
64
|
+
args[0] = request.protocol + ::ActionController::UrlWriter.default_url_options[:host] + args.first if args.first.is_a?(String) && !%r{^\w+://.*}.match(args.first) && !::ActionController::UrlWriter.default_url_options[:host].blank?
|
65
|
+
redirect_to_without_proxy(*args)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Sets the <tt>proxy_relative_url_root</tt> using the +parse_proxy_relative_url_root+ method
|
69
|
+
# to calculate it
|
70
|
+
#
|
71
|
+
# Sets the <tt>proxy_relative_url_root</tt> to nil if there aren't any forwarded uris
|
72
|
+
def set_proxy_relative_url_root
|
73
|
+
::ActionController::Base.proxy_relative_url_root = request.forwarded_uris.empty? ? nil : parse_proxy_relative_url_root
|
74
|
+
end
|
75
|
+
|
76
|
+
# Sets the <tt>default_url_options[:host]</tt> to the first forwarded host if there are any
|
77
|
+
#
|
78
|
+
# The original default host is restored after each request and can be accessed by calling
|
79
|
+
# <tt>ActionController::UrlWriter.default_url_options[:original_host]</tt>
|
80
|
+
def swap_default_host
|
81
|
+
::ActionController::UrlWriter.default_url_options[:original_host] = ::ActionController::UrlWriter.default_url_options[:host]
|
82
|
+
::ActionController::UrlWriter.default_url_options[:host] = request.forwarded_hosts.first unless request.forwarded_hosts.empty?
|
83
|
+
begin
|
84
|
+
yield
|
85
|
+
ensure
|
86
|
+
::ActionController::UrlWriter.default_url_options[:host] = ::ActionController::UrlWriter.default_url_options[:original_host]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Sets the <tt>relative_url_root</tt> to the <tt>proxy_relative_url_root</tt> unless it's nil
|
91
|
+
#
|
92
|
+
# The original relative url root is restored after each request and can be accessed by calling
|
93
|
+
# <tt>ActionController::Base.original_relative_url_root</tt>
|
94
|
+
def swap_relative_url_root
|
95
|
+
::ActionController::Base.original_relative_url_root = ::ActionController::Base.relative_url_root
|
96
|
+
::ActionController::Base.relative_url_root = ::ActionController::Base.proxy_relative_url_root unless ::ActionController::Base.proxy_relative_url_root.nil?
|
97
|
+
begin
|
98
|
+
yield
|
99
|
+
ensure
|
100
|
+
::ActionController::Base.relative_url_root = ::ActionController::Base.original_relative_url_root
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Sets the <tt>session_options[:session_domain]</tt> to the result of the +parse_session_domain+ method
|
105
|
+
# unless there aren't any forwarded hosts
|
106
|
+
#
|
107
|
+
# The original session domain is restored after each request and can be accessed by calling
|
108
|
+
# <tt>ActionController::Base.session_options[:original_session_domain]</tt>
|
109
|
+
def swap_session_domain
|
110
|
+
::ActionController::Base.session_options[:original_session_domain] = ::ActionController::Base.session_options[:session_domain]
|
111
|
+
::ActionController::Base.session_options[:session_domain] = parse_session_domain unless request.forwarded_hosts.empty?
|
112
|
+
begin
|
113
|
+
yield
|
114
|
+
ensure
|
115
|
+
::ActionController::Base.session_options[:session_domain] = ::ActionController::Base.session_options[:original_session_domain]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Huberry
|
2
|
+
module ActionController
|
3
|
+
module NamedRouteCollection
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval { alias_method_chain :define_url_helper, :proxy }
|
6
|
+
end
|
7
|
+
|
8
|
+
# Named route url helpers (not path helpers) don't seem to work correctly
|
9
|
+
# with forwarded hosts unless we explicitly set the option:
|
10
|
+
#
|
11
|
+
# :only_path => false
|
12
|
+
#
|
13
|
+
# This method only sets that option if it isn't set already
|
14
|
+
def define_url_helper_with_proxy(route, name, kind, options)
|
15
|
+
define_url_helper_without_proxy(route, name, kind, options)
|
16
|
+
if kind == :url
|
17
|
+
selector = url_helper_name(name, kind)
|
18
|
+
@module.module_eval do
|
19
|
+
define_method "#{selector}_with_proxy" do |*args|
|
20
|
+
args << {} unless args.last.is_a? Hash
|
21
|
+
args.last[:only_path] ||= false
|
22
|
+
send "#{selector}_without_proxy", *args
|
23
|
+
end
|
24
|
+
alias_method_chain selector, :proxy
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Huberry
|
2
|
+
module ActionController
|
3
|
+
module UrlRewriter
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval { alias_method_chain :rewrite_url, :proxy }
|
6
|
+
end
|
7
|
+
|
8
|
+
# Adds the default :host option unless already specified
|
9
|
+
#
|
10
|
+
# It will not set the :host option if <tt>options</tt> is not a hash or
|
11
|
+
# if the <tt>ActionController::UrlWriter.default_url_options[:host]</tt> is blank
|
12
|
+
def rewrite_url_with_proxy(options)
|
13
|
+
options[:host] ||= ::ActionController::UrlWriter.default_url_options[:host] if options.is_a?(Hash) && !::ActionController::UrlWriter.default_url_options[:host].blank?
|
14
|
+
rewrite_url_without_proxy(options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Huberry
|
2
|
+
module ActionView
|
3
|
+
module UrlHelper
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval { alias_method_chain :url_for, :proxy }
|
6
|
+
end
|
7
|
+
|
8
|
+
# Adds the default :host option unless already specified
|
9
|
+
#
|
10
|
+
# It will not set the :host option if <tt>options</tt> is not a hash or
|
11
|
+
# if the <tt>ActionController::UrlWriter.default_url_options[:host]</tt> is blank
|
12
|
+
def url_for_with_proxy(options = {})
|
13
|
+
options[:host] ||= ::ActionController::UrlWriter.default_url_options[:host] if options.is_a?(Hash) && !::ActionController::UrlWriter.default_url_options[:host].blank?
|
14
|
+
url_for_without_proxy(options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/init'
|
2
|
+
|
3
|
+
class AbstractRequestTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@request = ActionController::TestRequest.new
|
7
|
+
@request.host = 'example.com'
|
8
|
+
ActionController::UrlWriter.default_url_options[:host] = nil
|
9
|
+
ActionController::Base.relative_url_root = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_forwarded_hosts_should_be_empty
|
13
|
+
assert_equal [], @request.forwarded_hosts
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_parse_empty_forwarded_hosts_into_an_array
|
17
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = ''
|
18
|
+
assert_equal [], @request.forwarded_hosts
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_parse_nil_forwarded_hosts_into_an_array
|
22
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = nil
|
23
|
+
assert_equal [], @request.forwarded_hosts
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_forwarded_host_string_should_be_parsed_into_an_array
|
27
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = 'forwarded.com'
|
28
|
+
assert_equal ['forwarded.com'], @request.forwarded_hosts
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_comma_separated_forwarded_host_string_should_be_parsed_into_an_array
|
32
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = 'forwarded.com,something.com, test.com, testing.com'
|
33
|
+
assert_equal ['forwarded.com', 'something.com', 'test.com', 'testing.com'], @request.forwarded_hosts
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_forwarded_uris_should_be_empty
|
37
|
+
assert_equal [], @request.forwarded_uris
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_should_parse_empty_forwarded_uris_into_an_array
|
41
|
+
@request.env['HTTP_X_FORWARDED_URI'] = ''
|
42
|
+
assert_equal [], @request.forwarded_uris
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_should_parse_nil_forwarded_uris_into_an_array
|
46
|
+
@request.env['HTTP_X_FORWARDED_URI'] = nil
|
47
|
+
assert_equal [], @request.forwarded_uris
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_forwarded_uri_string_should_be_parsed_into_an_array
|
51
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing'
|
52
|
+
assert_equal ['/test/ing'], @request.forwarded_uris
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_comma_separated_forwarded_uri_string_should_be_parsed_into_an_array
|
56
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing,/whoa, /uh/oh, /mmm/kay'
|
57
|
+
assert_equal ['/test/ing', '/whoa', '/uh/oh', '/mmm/kay'], @request.forwarded_uris
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_be_able_to_use_custom_forwarded_uri_header_name
|
61
|
+
@original_header_name = ActionController::AbstractRequest.forwarded_uri_header_name
|
62
|
+
@request.env['HTTP_CUSTOM_FORWARDED_URI'] = '/test/ing'
|
63
|
+
ActionController::AbstractRequest.forwarded_uri_header_name = 'HTTP_CUSTOM_FORWARDED_URI'
|
64
|
+
assert_equal ['/test/ing'], @request.forwarded_uris
|
65
|
+
ActionController::AbstractRequest.forwarded_uri_header_name = @original_header_name
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/init'
|
2
|
+
|
3
|
+
class BaseTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@controller = TestController.new
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@request.host = 'example.com'
|
10
|
+
ActionController::UrlWriter.default_url_options[:host] = nil
|
11
|
+
ActionController::Base.relative_url_root = '/app'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_get_normal_action
|
15
|
+
get :normal_action
|
16
|
+
assert_equal "http://#{@request.host}/normal_action", @response.body
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_set_a_forwarded_host_as_a_default_host
|
20
|
+
add_forwarded_host_headers
|
21
|
+
get :normal_action
|
22
|
+
assert_equal "http://domain.com/app/normal_action", @response.body
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_set_forwarded_host_in_a_named_route
|
26
|
+
add_forwarded_host_headers
|
27
|
+
get :named_route_action
|
28
|
+
assert_equal "http://domain.com/app/normal_action", @response.body
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_restore_the_original_default_host
|
32
|
+
::ActionController::UrlWriter.default_url_options[:host] = 'some-other-domain.com'
|
33
|
+
add_forwarded_host_headers
|
34
|
+
get :normal_action
|
35
|
+
assert_equal "http://domain.com/app/normal_action", @response.body
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_url_generators_in_views_should_use_forwarded_host
|
39
|
+
add_forwarded_host_headers
|
40
|
+
get :view_action
|
41
|
+
assert_equal "/app/normal_action, http://domain.com/app/normal_action, http://domain.com/app/normal_action, /app/normal_action", @response.body
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_asset_tag_helpers_should_not_use_forwarded_host
|
45
|
+
add_forwarded_host_headers
|
46
|
+
get :asset_action
|
47
|
+
assert_nil(/domain\.com/.match(@response.body))
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_should_set_the_session_domain_with_a_forwarded_host
|
51
|
+
add_forwarded_host_headers
|
52
|
+
get :session_action
|
53
|
+
assert_equal '.domain.com', @response.body
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_restore_original_session_domain
|
57
|
+
::ActionController::Base.session_options[:session_domain] = '.example.com'
|
58
|
+
add_forwarded_host_headers
|
59
|
+
get :session_action
|
60
|
+
assert_equal '.domain.com', @response.body
|
61
|
+
assert_equal '.example.com', ::ActionController::Base.session_options[:session_domain]
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_should_restore_original_session_if_exception_is_raised
|
65
|
+
::ActionController::Base.session_options[:session_domain] = '.example.com'
|
66
|
+
add_forwarded_host_headers
|
67
|
+
assert_raises(RuntimeError) { get :exception_action }
|
68
|
+
assert_equal '.example.com', ::ActionController::Base.session_options[:session_domain]
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_should_restore_original_session_if_redirected
|
72
|
+
::ActionController::Base.session_options[:session_domain] = '.example.com'
|
73
|
+
add_forwarded_host_headers
|
74
|
+
get :redirect_action
|
75
|
+
assert_equal '.example.com', ::ActionController::Base.session_options[:session_domain]
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_should_restore_original_host_if_exception_is_raised
|
79
|
+
::ActionController::UrlWriter.default_url_options[:host] = 'some-other-domain.com'
|
80
|
+
add_forwarded_host_headers
|
81
|
+
assert_raises(RuntimeError) { get :exception_action }
|
82
|
+
assert_equal 'some-other-domain.com', ::ActionController::UrlWriter.default_url_options[:host]
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_should_restore_original_host_if_redirected
|
86
|
+
::ActionController::UrlWriter.default_url_options[:host] = 'some-other-domain.com'
|
87
|
+
add_forwarded_host_headers
|
88
|
+
get :redirect_action
|
89
|
+
assert_equal 'some-other-domain.com', ::ActionController::UrlWriter.default_url_options[:host]
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_get_normal_action
|
93
|
+
get :normal_action
|
94
|
+
assert_equal "http://#{@request.host}/app/normal_action", @response.body
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_should_swap_relative_url_root
|
98
|
+
add_forwarded_uri_headers
|
99
|
+
get :normal_action
|
100
|
+
assert_equal "http://#{@request.host}/test/ing/normal_action", @response.body
|
101
|
+
assert_equal '/app', ActionController::Base.relative_url_root
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_should_set_proxy_relative_url_root
|
105
|
+
add_forwarded_uri_headers
|
106
|
+
get :normal_action
|
107
|
+
assert_equal '/test/ing', ActionController::Base.proxy_relative_url_root
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_should_set_proxy_relative_url_root_in_a_named_route
|
111
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/named_route_action'
|
112
|
+
@request.env['PATH_INFO'] = '/named_route_action'
|
113
|
+
get :named_route_action
|
114
|
+
assert_equal "http://#{@request.host}/test/ing/normal_action", @response.body
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_should_set_original_relative_url_root
|
118
|
+
add_forwarded_uri_headers
|
119
|
+
get :normal_action
|
120
|
+
assert_equal '/app', ActionController::Base.original_relative_url_root
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_should_restore_relative_url_root_if_exception_is_raised
|
124
|
+
add_forwarded_uri_headers
|
125
|
+
assert_raises(RuntimeError) { get :exception_action }
|
126
|
+
assert_equal '/app', ActionController::Base.relative_url_root
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_should_restore_relative_url_root_if_exception_is_raised
|
130
|
+
add_forwarded_uri_headers
|
131
|
+
get :redirect_action
|
132
|
+
assert_equal '/app', ActionController::Base.relative_url_root
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_url_generators_in_views_should_use_forwarded_uri
|
136
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/view_action'
|
137
|
+
@request.env['PATH_INFO'] = '/view_action'
|
138
|
+
get :view_action
|
139
|
+
assert_equal "/test/ing/normal_action, http://example.com/test/ing/normal_action, /test/ing/normal_action, /test/ing/normal_action", @response.body
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_asset_tag_helpers_should_use_forwarded_uri
|
143
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/asset_action'
|
144
|
+
@request.env['PATH_INFO'] = '/asset_action'
|
145
|
+
get :asset_action
|
146
|
+
assert !@response.body.scan(/img[^>]+src\="\/test\/ing\/images\/test\.gif"/).empty?
|
147
|
+
assert !@response.body.scan(/script[^>]+src\="\/test\/ing\/javascripts\/test\.js"/).empty?
|
148
|
+
assert !@response.body.scan(/link[^>]+href\="\/test\/ing\/stylesheets\/test\.css"/).empty?
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_should_use_forwarded_host_in_a_redirect
|
152
|
+
add_forwarded_host_headers
|
153
|
+
get :redirect_action
|
154
|
+
assert_redirected_to 'http://domain.com/app/normal_action'
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_should_use_forwarded_host_in_a_redirect_with_named_routes
|
158
|
+
add_forwarded_host_headers
|
159
|
+
get :redirect_with_named_route_action
|
160
|
+
assert_redirected_to 'http://domain.com/app/normal_action'
|
161
|
+
end
|
162
|
+
|
163
|
+
protected
|
164
|
+
|
165
|
+
def add_forwarded_host_headers
|
166
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = 'domain.com'
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_forwarded_uri_headers
|
170
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/normal_action'
|
171
|
+
@request.env['PATH_INFO'] = '/normal_action'
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/init'
|
2
|
+
|
3
|
+
class NamedRouteCollectionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@controller = TestController.new
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@request.host = 'example.com'
|
10
|
+
ActionController::UrlWriter.default_url_options[:host] = nil
|
11
|
+
ActionController::Base.relative_url_root = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_alias_method_chain_url_helpers
|
15
|
+
[ActionController::Base, ActionView::Base].each do |klass|
|
16
|
+
assert klass.method_defined?(:normal_action_url_with_proxy)
|
17
|
+
assert klass.method_defined?(:normal_action_url_without_proxy)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_not_alias_method_chain_path_helpers
|
22
|
+
[ActionController::Base, ActionView::Base].each do |klass|
|
23
|
+
assert !klass.method_defined?(:normal_action_path_with_proxy)
|
24
|
+
assert !klass.method_defined?(:normal_action_path_without_proxy)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/init'
|
2
|
+
|
3
|
+
class UrlHelperTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@controller = TestController.new
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@request.host = 'example.com'
|
10
|
+
ActionController::UrlWriter.default_url_options[:host] = nil
|
11
|
+
ActionController::Base.relative_url_root = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_render_urls_normally
|
15
|
+
get :view_action
|
16
|
+
assert_equal '/normal_action, http://example.com/normal_action, /normal_action, /normal_action', @response.body
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_render_urls_with_forwarded_hosts_while_respecting_the_only_path_option
|
20
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = 'domain.com'
|
21
|
+
get :view_action
|
22
|
+
assert_equal '/normal_action, http://domain.com/normal_action, http://domain.com/normal_action, /normal_action', @response.body
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_render_urls_with_forwarded_uris
|
26
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/view_action'
|
27
|
+
@request.env['PATH_INFO'] = '/view_action'
|
28
|
+
get :view_action
|
29
|
+
assert_equal '/test/ing/normal_action, http://example.com/test/ing/normal_action, /test/ing/normal_action, /test/ing/normal_action', @response.body
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_should_render_urls_with_forwarded_hosts_and_uris
|
33
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = 'domain.com'
|
34
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/view_action'
|
35
|
+
@request.env['PATH_INFO'] = '/view_action'
|
36
|
+
get :view_action
|
37
|
+
assert_equal '/test/ing/normal_action, http://domain.com/test/ing/normal_action, http://domain.com/test/ing/normal_action, /test/ing/normal_action', @response.body
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/init'
|
2
|
+
|
3
|
+
class UrlRewriter < ::ActionController::UrlRewriter
|
4
|
+
public
|
5
|
+
def rewrite_url
|
6
|
+
super :action => :normal_action, :controller => :test
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class UrlRewriterTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@controller = TestController.new
|
14
|
+
@request = ActionController::TestRequest.new
|
15
|
+
@response = ActionController::TestResponse.new
|
16
|
+
@request.host = 'example.com'
|
17
|
+
@url_rewriter = UrlRewriter.new(@request, {})
|
18
|
+
ActionController::UrlWriter.default_url_options[:host] = nil
|
19
|
+
ActionController::Base.relative_url_root = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_rewrite_normal_action_with_request_host
|
23
|
+
assert_equal 'http://example.com/normal_action', @url_rewriter.rewrite_url
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_should_rewrite_normal_action_with_request_host_if_default_host_is_empty
|
27
|
+
ActionController::UrlWriter.default_url_options[:host] = ''
|
28
|
+
assert_equal 'http://example.com/normal_action', @url_rewriter.rewrite_url
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_rewrite_normal_action_with_default_host
|
32
|
+
ActionController::UrlWriter.default_url_options[:host] = 'test.com'
|
33
|
+
assert_equal 'http://test.com/normal_action', @url_rewriter.rewrite_url
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shuber-proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Huber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-11-14 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A gem/plugin that allows rails applications to dynamically respond to proxied requests by detecting forwarded host/uri headers and setting the session domain, default host, and relative url root
|
17
|
+
email: shuber@huberry.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- CHANGELOG
|
26
|
+
- init.rb
|
27
|
+
- lib/huberry/action_controller/abstract_request.rb
|
28
|
+
- lib/huberry/action_controller/base.rb
|
29
|
+
- lib/huberry/action_controller/named_route_collection.rb
|
30
|
+
- lib/huberry/action_controller/url_rewriter.rb
|
31
|
+
- lib/huberry/action_view/url_helper.rb
|
32
|
+
- lib/huberry/proxy.rb
|
33
|
+
- MIT-LICENSE
|
34
|
+
- Rakefile
|
35
|
+
- README.markdown
|
36
|
+
has_rdoc: false
|
37
|
+
homepage: http://github.com/shuber/proxy
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --line-numbers
|
41
|
+
- --inline-source
|
42
|
+
- --main
|
43
|
+
- README.markdown
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.2.0
|
62
|
+
signing_key:
|
63
|
+
specification_version: 2
|
64
|
+
summary: A gem/plugin that allows rails applications to dynamically respond to proxied requests
|
65
|
+
test_files:
|
66
|
+
- test/abstract_request_test.rb
|
67
|
+
- test/base_test.rb
|
68
|
+
- test/named_route_collection_test.rb
|
69
|
+
- test/url_helper_test.rb
|
70
|
+
- test/url_rewriter_test.rb
|