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 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