hybridgroup-proxy 1.3.6
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 +98 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +90 -0
- data/Rakefile +34 -0
- data/init.rb +1 -0
- data/lib/proxy.rb +55 -0
- data/lib/proxy/action_controller/abstract_request.rb +46 -0
- data/lib/proxy/action_controller/base.rb +130 -0
- data/lib/proxy/action_controller/named_route_collection.rb +30 -0
- data/lib/proxy/action_controller/url_rewriter.rb +21 -0
- data/lib/proxy/action_view/url_helper.rb +21 -0
- data/test/abstract_request_test.rb +68 -0
- data/test/base_test.rb +182 -0
- data/test/init.rb +103 -0
- data/test/named_route_collection_test.rb +28 -0
- data/test/proxy_test.rb +34 -0
- data/test/url_helper_test.rb +40 -0
- data/test/url_rewriter_test.rb +36 -0
- metadata +74 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
2009-06-05 - Sean Huber (shuber@huberry.com)
|
2
|
+
* Fix bug with passenger
|
3
|
+
* Append http host instead of replacing
|
4
|
+
|
5
|
+
2009-06-05 - Sean Huber (shuber@huberry.com)
|
6
|
+
* Add multiple domain support for rack
|
7
|
+
* Update gemspec
|
8
|
+
* Update README
|
9
|
+
|
10
|
+
2009-06-04 - Sean Huber (shuber@huberry.com)
|
11
|
+
* Update test related rake tasks
|
12
|
+
* Remove huberry namespace
|
13
|
+
* Add support for multiple domains
|
14
|
+
* Update README
|
15
|
+
|
16
|
+
2009-05-20 - Sean Huber (shuber@huberry.com)
|
17
|
+
* Update date in gemspec so github rebuilds gem
|
18
|
+
|
19
|
+
2009-05-18 - Sean Huber (shuber@huberry.com)
|
20
|
+
* Fix compatibility issues with actionpack >= 2.2.2
|
21
|
+
|
22
|
+
2009-01-24 - Sean Huber (shuber@huberry.com)
|
23
|
+
* Add compatibility for edge/upcoming rails versions
|
24
|
+
|
25
|
+
2009-01-08 - Sean Huber (shuber@huberry.com)
|
26
|
+
* Add Proxy namespace
|
27
|
+
* Remove .gitignore
|
28
|
+
|
29
|
+
2008-12-09 - Sean Huber (shuber@huberry.com)
|
30
|
+
* Update README
|
31
|
+
|
32
|
+
2008-12-08 - Sean Huber (shuber@huberry.com)
|
33
|
+
* Fix bug - lib/proxy.rb was not included in gemspec
|
34
|
+
|
35
|
+
2008-11-14 - Sean Huber (shuber@huberry.com)
|
36
|
+
* Fix bug - "redirect_to some_path" now uses a forwarded host if it exists
|
37
|
+
* Gemify
|
38
|
+
* Update README
|
39
|
+
* Update proxy.gemspec
|
40
|
+
|
41
|
+
2008-10-30 - Sean Huber (shuber@huberry.com)
|
42
|
+
* Update documentation
|
43
|
+
* Move the logic that calculates the session_domain into its own method and update documentation
|
44
|
+
* Update README
|
45
|
+
|
46
|
+
2008-10-27 - Sean Huber (shuber@huberry.com)
|
47
|
+
* rewrite_url also adds the :host option as options is a Hash
|
48
|
+
* Move the logic that calculates the proxy_relative_url_root into its own method
|
49
|
+
|
50
|
+
2008-10-21 - Sean Huber (shuber@huberry.com)
|
51
|
+
* Fix bug - only add the :host option to url_helper if options is a Hash
|
52
|
+
|
53
|
+
2008-10-06 - Sean Huber (shuber@huberry.com)
|
54
|
+
* Add tests to ensure asset helpers work correctly
|
55
|
+
|
56
|
+
2008-10-05 - Sean Huber (shuber@huberry.com)
|
57
|
+
* Add failing named route test
|
58
|
+
* Named routes now work with forwarded hosts
|
59
|
+
* ActionView::Base#url_for uses forwarded hosts correctly
|
60
|
+
* Update README
|
61
|
+
* Update init.rb
|
62
|
+
|
63
|
+
2008-10-03 - Sean Huber (shuber@huberry.com)
|
64
|
+
* Add tests to ensure default host and relative_url_root are restored when an action redirects
|
65
|
+
* Update README
|
66
|
+
* The original session_domain is now restored after each request
|
67
|
+
|
68
|
+
2008-10-02 - Sean Huber (shuber@huberry.com)
|
69
|
+
* Remove Dispatcher and moved that logic into Base
|
70
|
+
* Add Rakefile
|
71
|
+
* Fix bug - referred to ActionController instead of ActionController::Base
|
72
|
+
* Fix bug - plugin was not being loaded properly
|
73
|
+
* Update README
|
74
|
+
* Fix bug - proxy_relative_url_root was not being set on every request
|
75
|
+
* Fix bug - relative_url_root was always being delegated to ActionController::AbstractRequest
|
76
|
+
|
77
|
+
2008-10-01 - Sean Huber (shuber@huberry.com)
|
78
|
+
* Move some forwarded host logic into AbstractRequest
|
79
|
+
* Add AbstractRequest tests and renamed BaseTest file
|
80
|
+
* Add more AbstractRequest tests
|
81
|
+
* ActionController::Base will delegate relative_url_root to AbstractRequest if necessary to support older versions of actionpack
|
82
|
+
* Add more Base tests
|
83
|
+
* Reorder requires and inclusions in proxy.rb
|
84
|
+
* Update CHANGELOG
|
85
|
+
* Update README
|
86
|
+
* Add UrlRewriter
|
87
|
+
* Add more tests
|
88
|
+
|
89
|
+
2008-09-29 - Sean Huber (shuber@huberry.com)
|
90
|
+
* Initial import
|
91
|
+
* Add some tests - still need to figure out how to test Dispatcher
|
92
|
+
* Base automatically detects HTTP_X_FORWARDED_URI and determines relative_url_root (can be overwritten)
|
93
|
+
* Update Base tests
|
94
|
+
* Base can now parse a comma separated string of forwarded uris
|
95
|
+
* The HTTP_X_FORWARDED_URI variable name can be changed to something else
|
96
|
+
* Update README
|
97
|
+
* Regex to determine relative root url is now properly escaped
|
98
|
+
* 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,90 @@
|
|
1
|
+
# Proxy
|
2
|
+
|
3
|
+
A gem/plugin that allows rails applications to dynamically respond to multiple domains and 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.
|
4
|
+
|
5
|
+
The original session domain, default host, and relative url root will be restored after each request.
|
6
|
+
|
7
|
+
Requires actionpack >= 2.0.0
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
script/plugin install git://github.com/shuber/proxy.git
|
13
|
+
OR
|
14
|
+
gem install proxy
|
15
|
+
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
### Proxied Requests
|
20
|
+
|
21
|
+
Let's 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:
|
22
|
+
|
23
|
+
http://client.example.com/orders
|
24
|
+
|
25
|
+
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:
|
26
|
+
|
27
|
+
http://clientdomain.com/orders
|
28
|
+
|
29
|
+
This plugin will automatically detect this forwarded host and set the session domain and default host (for url generation) accordingly.
|
30
|
+
|
31
|
+
|
32
|
+
### Proxied Requests with Custom URIs
|
33
|
+
|
34
|
+
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:
|
35
|
+
|
36
|
+
http://clientdomain.com/neworders
|
37
|
+
|
38
|
+
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.
|
39
|
+
|
40
|
+
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:
|
41
|
+
|
42
|
+
ActionController::AbstractRequest.forwarded_uri_header_name = 'SOME_CUSTOM_HEADER_NAME'
|
43
|
+
|
44
|
+
You can add that line in environment.rb or an initializer.
|
45
|
+
|
46
|
+
|
47
|
+
#### Relative Url Root Proxy Setup
|
48
|
+
|
49
|
+
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:
|
50
|
+
|
51
|
+
RewriteRule ^neworders(.*) http://client.example.com/orders$1 [P,QSA,L,E=originalUri:%{REQUEST_URI}]
|
52
|
+
RequestHeader append X_FORWARDED_URI %{originalUri}e e=originalUri
|
53
|
+
|
54
|
+
|
55
|
+
### Multiple Domains
|
56
|
+
|
57
|
+
Imagine you have a CMS that hosts multiple client sites. You want your users to manage their sites on your root domain `http://yourcmsapp.com` and you display a site's public content when it's accessed by its subdomain (e.g. `http://cool-site.yourcmsapp.com`). You'll probably be using [subdomain-fu](http://github.com/mbleigh/subdomain-fu) so you can route based on subdomains like:
|
58
|
+
|
59
|
+
ActionController::Routing::Routes.draw do |map|
|
60
|
+
# this routing controller has a before_filter callback that looks up a site by subdomain
|
61
|
+
map.public_page '*path', :controller => 'routing', :conditions => { :subdomain => /^[^\.]+$/ }
|
62
|
+
|
63
|
+
map.with_options :conditions => { :subdomain => nil } do |admin|
|
64
|
+
admin.resource :account, :controller => 'account'
|
65
|
+
admin.resources :sites
|
66
|
+
...
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
Now, it gets tricky if you want `http://cool-site.com` to render `cool-site`'s public content because you can't tell if this request has a subdomain or not. In order for your routes to work, you must have all requests coming in from your domain `yourcmsapp.com`. You can accomplish this by calling the `Proxy.replace_host_with(&block)` method like so:
|
71
|
+
|
72
|
+
# config/initializers/proxy.rb
|
73
|
+
|
74
|
+
Proxy.replace_host_with do |request|
|
75
|
+
"#{Site.find_by_domain(request.host).try(:subdomain) || '-INVALID-'}.yourcmsapp.com" unless request.host =~ /(\.|^)yourcmsapp.com$/i
|
76
|
+
end
|
77
|
+
|
78
|
+
Let's examine what this block is doing:
|
79
|
+
|
80
|
+
* First, it checks if the current request's host is already on your domain. If it is, we don't need to do anything, otherwise...
|
81
|
+
* It checks if a site exists with a domain that matches the current request's host.
|
82
|
+
* If a site does exist, a new host is returned using the site's `subdomain` with your app domain and everything renders fine, otherwise...
|
83
|
+
* A fake host is returned (-INVALID-.yourcmsapp.com), and the request 404s once it gets to your `routing` controller and a site can't be found with the subdomain `-INVALID-`
|
84
|
+
|
85
|
+
If `nil, false, or an empty string` is returned when you call the `Proxy.replace_host_with` method, the current request's host is not modified. Otherwise, the `HTTP_X_FORWARDED_HOST` request header is set to: `"#{the_original_host}, #{the_new_host}"`. This allows your routes to use your domain when evaluating routing conditions and also allows all of the application's url generators to use the original host.
|
86
|
+
|
87
|
+
|
88
|
+
## Contact
|
89
|
+
|
90
|
+
Problems, comments, and suggestions all welcome: [shuber@huberry.com](mailto:shuber@huberry.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
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
|
+
namespace :test do
|
9
|
+
desc 'Default: run the proxy tests for all versions of actionpack'
|
10
|
+
task :all do
|
11
|
+
versions = `gem list`.match(/actionpack \((.+)\)/).captures[0].split(/, /).select { |v| v[0,1].to_i > 1 }
|
12
|
+
versions.each do |version|
|
13
|
+
puts "\n\n============================================================="
|
14
|
+
puts "TESTING WITH ACTION PACK VERSION #{version}\n\n"
|
15
|
+
system "rake test ACTION_PACK_VERSION=#{version}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Test the proxy plugin.'
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
22
|
+
t.libs << 'lib'
|
23
|
+
t.pattern = 'test/*_test.rb'
|
24
|
+
t.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Generate documentation for the proxy plugin.'
|
28
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
29
|
+
rdoc.rdoc_dir = 'rdoc'
|
30
|
+
rdoc.title = 'Proxy'
|
31
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
32
|
+
rdoc.rdoc_files.include('README.markdown')
|
33
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
34
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_dependency 'proxy'
|
data/lib/proxy.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'proxy/action_controller/abstract_request'
|
2
|
+
require 'proxy/action_controller/base'
|
3
|
+
require 'proxy/action_controller/named_route_collection'
|
4
|
+
require 'proxy/action_controller/url_rewriter'
|
5
|
+
require 'proxy/action_view/url_helper'
|
6
|
+
|
7
|
+
module Proxy
|
8
|
+
mattr_accessor :replace_host_with_proc
|
9
|
+
self.replace_host_with_proc = proc { |request| }
|
10
|
+
|
11
|
+
def self.replace_host_with(&block)
|
12
|
+
self.replace_host_with_proc = block
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.before_dispatch(dispatcher)
|
18
|
+
request = dispatcher.instance_variable_get('@request') || dispatcher.instance_variable_get('@env')
|
19
|
+
request = Rack::Request.new(request) if request.is_a?(Hash)
|
20
|
+
new_host = replace_host_with_proc.call(request)
|
21
|
+
if /([^\.]+\.[^\.]+)$/.match(request.host)
|
22
|
+
original_host = ".#{$1}"
|
23
|
+
else
|
24
|
+
original_host = request.host
|
25
|
+
end
|
26
|
+
request.env['rack.session.options'].merge!(:domain => original_host) # force cookie that matches original domain without subdomain
|
27
|
+
request.env['HTTP_X_FORWARDED_HOST'] = [request.host, new_host].join(', ') unless new_host.blank?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ActionController::Dispatcher.before_dispatch do |dispatcher|
|
32
|
+
Proxy.send :before_dispatch, dispatcher
|
33
|
+
end
|
34
|
+
|
35
|
+
ActionController::AbstractRequest = ActionController::Request if defined?(ActionController::Request)
|
36
|
+
ActionController::AbstractRequest.send :include, Proxy::ActionController::AbstractRequest
|
37
|
+
ActionController::Base.send :include, Proxy::ActionController::Base
|
38
|
+
ActionController::Routing::RouteSet::NamedRouteCollection.send :include, Proxy::ActionController::NamedRouteCollection
|
39
|
+
ActionController::UrlRewriter.send :include, Proxy::ActionController::UrlRewriter
|
40
|
+
ActionView::Base.send :include, Proxy::ActionView::UrlHelper
|
41
|
+
|
42
|
+
unless ActionController::UrlWriter.respond_to?(:default_url_options)
|
43
|
+
ActionController::Base.class_eval do
|
44
|
+
include ActionController::UrlWriter
|
45
|
+
|
46
|
+
def default_url_options_with_backwards_compatibility(*args)
|
47
|
+
default_url_options_without_backwards_compatibility
|
48
|
+
end
|
49
|
+
alias_method_chain :default_url_options, :backwards_compatibility
|
50
|
+
end
|
51
|
+
|
52
|
+
class << ActionController::UrlWriter
|
53
|
+
delegate :default_url_options, :default_url_options=, :to => ::ActionController::Base
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Proxy
|
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
|
+
hosts = env['HTTP_X_FORWARDED_HOST'].to_s.split(/,\s*/)
|
24
|
+
unless hosts.empty? || hosts.first != hosts.last
|
25
|
+
hosts << env['HTTP_HOST'] unless env['HTTP_HOST'].blank?
|
26
|
+
env['HTTP_X_FORWARDED_HOST'] = hosts.join(', ')
|
27
|
+
end
|
28
|
+
hosts
|
29
|
+
end
|
30
|
+
|
31
|
+
# Parses the forwarded uri header and returns an array of forwarded uris
|
32
|
+
#
|
33
|
+
# For example:
|
34
|
+
#
|
35
|
+
# If the HTTP_X_FORWARDED_URI header was set to
|
36
|
+
# '/some/path, /some/other/path, /and/another/path'
|
37
|
+
#
|
38
|
+
# This method would return ['/some/path, '/some/other/path', '/and/another/path']
|
39
|
+
#
|
40
|
+
# Returns an empty array if there aren't any forwarded uris
|
41
|
+
def forwarded_uris
|
42
|
+
env[self.forwarded_uri_header_name].to_s.split(/,\s*/)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Proxy
|
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
|
+
alias_method_chain :redirect_to, :proxy
|
13
|
+
class << self; delegate :relative_url_root, :relative_url_root=, :to => ::ActionController::AbstractRequest unless ::ActionController::Base.respond_to?(:relative_url_root); end
|
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 + url_options[:host] + args.first if args.first.is_a?(String) && !%r{^\w+://.*}.match(args.first) && !url_options[:host].blank?
|
65
|
+
redirect_to_without_proxy(*args)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns ::ActionController::Base.session_options
|
69
|
+
def session_options
|
70
|
+
::ActionController::Base.session_options
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sets the <tt>proxy_relative_url_root</tt> using the +parse_proxy_relative_url_root+ method
|
74
|
+
# to calculate it
|
75
|
+
#
|
76
|
+
# Sets the <tt>proxy_relative_url_root</tt> to nil if there aren't any forwarded uris
|
77
|
+
def set_proxy_relative_url_root
|
78
|
+
::ActionController::Base.proxy_relative_url_root = request.forwarded_uris.empty? ? nil : parse_proxy_relative_url_root
|
79
|
+
end
|
80
|
+
|
81
|
+
# Sets the <tt>default_url_options[:host]</tt> to the first forwarded host if there are any
|
82
|
+
#
|
83
|
+
# The original default host is restored after each request and can be accessed by calling
|
84
|
+
# <tt>ActionController::UrlWriter.default_url_options[:original_host]</tt>
|
85
|
+
def swap_default_host
|
86
|
+
url_options[:original_host] = url_options[:host]
|
87
|
+
url_options[:host] = request.forwarded_hosts.first unless request.forwarded_hosts.empty?
|
88
|
+
begin
|
89
|
+
yield
|
90
|
+
ensure
|
91
|
+
url_options[:host] = url_options[:original_host]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Sets the <tt>relative_url_root</tt> to the <tt>proxy_relative_url_root</tt> unless it's nil
|
96
|
+
#
|
97
|
+
# The original relative url root is restored after each request and can be accessed by calling
|
98
|
+
# <tt>ActionController::Base.original_relative_url_root</tt>
|
99
|
+
def swap_relative_url_root
|
100
|
+
::ActionController::Base.original_relative_url_root = ::ActionController::Base.relative_url_root
|
101
|
+
::ActionController::Base.relative_url_root = ::ActionController::Base.proxy_relative_url_root unless ::ActionController::Base.proxy_relative_url_root.nil?
|
102
|
+
begin
|
103
|
+
yield
|
104
|
+
ensure
|
105
|
+
::ActionController::Base.relative_url_root = ::ActionController::Base.original_relative_url_root
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Sets the <tt>session_options[:session_domain]</tt> to the result of the +parse_session_domain+ method
|
110
|
+
# unless there aren't any forwarded hosts
|
111
|
+
#
|
112
|
+
# The original session domain is restored after each request and can be accessed by calling
|
113
|
+
# <tt>ActionController::Base.session_options[:original_session_domain]</tt>
|
114
|
+
def swap_session_domain
|
115
|
+
session_options[:original_session_domain] = session_options[:session_domain] || session_options[:domain]
|
116
|
+
session_options[:session_domain] = session_options[:domain] = parse_session_domain unless request.forwarded_hosts.empty?
|
117
|
+
begin
|
118
|
+
yield
|
119
|
+
ensure
|
120
|
+
session_options[:session_domain] = session_options[:domain] = session_options[:original_session_domain]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Returns ::ActionController::UrlWriter.default_url_options
|
125
|
+
def url_options
|
126
|
+
::ActionController::UrlWriter.default_url_options
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Proxy
|
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,21 @@
|
|
1
|
+
module Proxy
|
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
|
+
if options.is_a?(Hash)
|
14
|
+
options[:host] ||= ::ActionController::UrlWriter.default_url_options[:host] unless ::ActionController::UrlWriter.default_url_options[:host].blank?
|
15
|
+
options.delete(:original_host)
|
16
|
+
end
|
17
|
+
rewrite_url_without_proxy(options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Proxy
|
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
|
+
if options.is_a?(Hash)
|
14
|
+
options[:host] ||= ::ActionController::UrlWriter.default_url_options[:host] unless ::ActionController::UrlWriter.default_url_options[:host].blank?
|
15
|
+
options.delete(:original_host)
|
16
|
+
end
|
17
|
+
url_for_without_proxy(options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
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,182 @@
|
|
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_domain_with_domain_key
|
65
|
+
::ActionController::Base.session_options[:domain] = '.example.com'
|
66
|
+
add_forwarded_host_headers
|
67
|
+
get :session_action
|
68
|
+
assert_equal '.domain.com', @response.body
|
69
|
+
assert_equal '.example.com', ::ActionController::Base.session_options[:domain]
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_should_restore_original_session_if_exception_is_raised
|
73
|
+
::ActionController::Base.session_options[:session_domain] = '.example.com'
|
74
|
+
add_forwarded_host_headers
|
75
|
+
assert_raises(RuntimeError) { get :exception_action }
|
76
|
+
assert_equal '.example.com', ::ActionController::Base.session_options[:session_domain]
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_should_restore_original_session_if_redirected
|
80
|
+
::ActionController::Base.session_options[:session_domain] = '.example.com'
|
81
|
+
add_forwarded_host_headers
|
82
|
+
get :redirect_action
|
83
|
+
assert_equal '.example.com', ::ActionController::Base.session_options[:session_domain]
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_should_restore_original_host_if_exception_is_raised
|
87
|
+
::ActionController::UrlWriter.default_url_options[:host] = 'some-other-domain.com'
|
88
|
+
add_forwarded_host_headers
|
89
|
+
assert_raises(RuntimeError) { get :exception_action }
|
90
|
+
assert_equal 'some-other-domain.com', ::ActionController::UrlWriter.default_url_options[:host]
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_should_restore_original_host_if_redirected
|
94
|
+
::ActionController::UrlWriter.default_url_options[:host] = 'some-other-domain.com'
|
95
|
+
add_forwarded_host_headers
|
96
|
+
get :redirect_action
|
97
|
+
assert_equal 'some-other-domain.com', ::ActionController::UrlWriter.default_url_options[:host]
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_should_get_normal_action
|
101
|
+
get :normal_action
|
102
|
+
assert_equal "http://#{@request.host}/app/normal_action", @response.body
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_should_swap_relative_url_root
|
106
|
+
add_forwarded_uri_headers
|
107
|
+
get :normal_action
|
108
|
+
assert_equal "http://#{@request.host}/test/ing/normal_action", @response.body
|
109
|
+
assert_equal '/app', ActionController::Base.relative_url_root
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_should_set_proxy_relative_url_root
|
113
|
+
add_forwarded_uri_headers
|
114
|
+
get :normal_action
|
115
|
+
assert_equal '/test/ing', ActionController::Base.proxy_relative_url_root
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_should_set_proxy_relative_url_root_in_a_named_route
|
119
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/named_route_action'
|
120
|
+
@request.env['PATH_INFO'] = '/named_route_action'
|
121
|
+
get :named_route_action
|
122
|
+
assert_equal "http://#{@request.host}/test/ing/normal_action", @response.body
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_should_set_original_relative_url_root
|
126
|
+
add_forwarded_uri_headers
|
127
|
+
get :normal_action
|
128
|
+
assert_equal '/app', ActionController::Base.original_relative_url_root
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_should_restore_relative_url_root_if_exception_is_raised
|
132
|
+
add_forwarded_uri_headers
|
133
|
+
assert_raises(RuntimeError) { get :exception_action }
|
134
|
+
assert_equal '/app', ActionController::Base.relative_url_root
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_should_restore_relative_url_root_if_exception_is_raised
|
138
|
+
add_forwarded_uri_headers
|
139
|
+
get :redirect_action
|
140
|
+
assert_equal '/app', ActionController::Base.relative_url_root
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_url_generators_in_views_should_use_forwarded_uri
|
144
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/view_action'
|
145
|
+
@request.env['PATH_INFO'] = '/view_action'
|
146
|
+
get :view_action
|
147
|
+
assert_equal "/test/ing/normal_action, http://example.com/test/ing/normal_action, /test/ing/normal_action, /test/ing/normal_action", @response.body
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_asset_tag_helpers_should_use_forwarded_uri
|
151
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/asset_action'
|
152
|
+
@request.env['PATH_INFO'] = '/asset_action'
|
153
|
+
get :asset_action
|
154
|
+
assert !@response.body.scan(/img[^>]+src\="\/test\/ing\/images\/test\.gif"/).empty?
|
155
|
+
assert !@response.body.scan(/script[^>]+src\="\/test\/ing\/javascripts\/test\.js"/).empty?
|
156
|
+
assert !@response.body.scan(/link[^>]+href\="\/test\/ing\/stylesheets\/test\.css"/).empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_should_use_forwarded_host_in_a_redirect
|
160
|
+
add_forwarded_host_headers
|
161
|
+
get :redirect_action
|
162
|
+
assert_redirected_to 'http://domain.com/app/normal_action'
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_should_use_forwarded_host_in_a_redirect_with_named_routes
|
166
|
+
add_forwarded_host_headers
|
167
|
+
get :redirect_with_named_route_action
|
168
|
+
assert_redirected_to 'http://domain.com/app/normal_action'
|
169
|
+
end
|
170
|
+
|
171
|
+
protected
|
172
|
+
|
173
|
+
def add_forwarded_host_headers
|
174
|
+
@request.env['HTTP_X_FORWARDED_HOST'] = 'domain.com'
|
175
|
+
end
|
176
|
+
|
177
|
+
def add_forwarded_uri_headers
|
178
|
+
@request.env['HTTP_X_FORWARDED_URI'] = '/test/ing/normal_action'
|
179
|
+
@request.env['PATH_INFO'] = '/normal_action'
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
data/test/init.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
$:.reject! { |path| path.include? 'TextMate' }
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
# Load rubygems
|
5
|
+
#
|
6
|
+
require 'rubygems'
|
7
|
+
|
8
|
+
# Load ActionPack
|
9
|
+
#
|
10
|
+
args = ['actionpack']
|
11
|
+
args << ENV['ACTION_PACK_VERSION'] if ENV['ACTION_PACK_VERSION']
|
12
|
+
gem *args
|
13
|
+
require 'action_pack'
|
14
|
+
require 'action_controller'
|
15
|
+
require 'action_controller/dispatcher'
|
16
|
+
require 'action_controller/routing'
|
17
|
+
require 'action_controller/session_management'
|
18
|
+
require 'action_controller/url_rewriter'
|
19
|
+
require 'action_controller/test_process'
|
20
|
+
require 'action_view'
|
21
|
+
|
22
|
+
Test::Unit::TestCase.class_eval do
|
23
|
+
include ActionController::TestProcess
|
24
|
+
|
25
|
+
unless instance_methods.include?('assert_redirected_to')
|
26
|
+
def assert_redirected_to(url)
|
27
|
+
assert @response.redirect?
|
28
|
+
assert_equal url, @response.location
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Routing
|
34
|
+
#
|
35
|
+
class ActionController::Routing::RouteSet
|
36
|
+
def append
|
37
|
+
yield Mapper.new(self)
|
38
|
+
install_helpers
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
ActionController::Base.session_options.merge! :key => '_proxy_session', :secret => '60447f093cd3f5d57686dd5ca1ced83216c846047db0ec97480a5e85411d9bd41ec5587cc4aafac27a4f0e649f0c628b0955b315856b78787a96168671dc96d4'
|
43
|
+
|
44
|
+
# Require the main proxy.rb file
|
45
|
+
#
|
46
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'lib', 'proxy')
|
47
|
+
|
48
|
+
# Test controller
|
49
|
+
#
|
50
|
+
class TestController < ActionController::Base
|
51
|
+
|
52
|
+
def asset_action
|
53
|
+
render :inline => '<%= image_tag "test.gif" %>, <%= javascript_include_tag "test" %>, <%= stylesheet_link_tag "test" %>'
|
54
|
+
end
|
55
|
+
|
56
|
+
def exception_action
|
57
|
+
raise 'Uh oh'
|
58
|
+
end
|
59
|
+
|
60
|
+
def named_route_action
|
61
|
+
render :text => normal_action_url
|
62
|
+
end
|
63
|
+
|
64
|
+
def normal_action
|
65
|
+
render :text => url_for(:controller => 'test', :action => 'normal_action')
|
66
|
+
end
|
67
|
+
|
68
|
+
def redirect_action
|
69
|
+
redirect_to :action => 'normal_action'
|
70
|
+
end
|
71
|
+
|
72
|
+
def redirect_with_named_route_action
|
73
|
+
redirect_to normal_action_path
|
74
|
+
end
|
75
|
+
|
76
|
+
def session_action
|
77
|
+
render :text => ActionController::Base.session_options[:session_domain]
|
78
|
+
end
|
79
|
+
|
80
|
+
def view_action
|
81
|
+
render :inline => '<%= normal_action_path %>, <%= normal_action_url %>, <%= url_for(:controller => "test", :action => "normal_action") %>, <%= url_for(:controller => "test", :action => "normal_action", :only_path => true) %>'
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def rescue_action(e)
|
87
|
+
raise e
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Test routes
|
92
|
+
#
|
93
|
+
ActionController::Routing::Routes.append do |map|
|
94
|
+
map.connect 'asset_action', :controller => 'test', :action => 'asset_action'
|
95
|
+
map.connect 'exception_action', :controller => 'test', :action => 'exception_action'
|
96
|
+
map.connect 'named_route_action', :controller => 'test', :action => 'named_route_action'
|
97
|
+
map.connect 'normal_action', :controller => 'test', :action => 'normal_action'
|
98
|
+
map.connect 'redirect_action', :controller => 'test', :action => 'redirect_action'
|
99
|
+
map.connect 'redirect_with_named_route_action', :controller => 'test', :action => 'redirect_with_named_route_action'
|
100
|
+
map.connect 'session_action', :controller => 'test', :action => 'session_action'
|
101
|
+
map.connect 'view_action', :controller => 'test', :action => 'view_action'
|
102
|
+
map.normal_action 'normal_action', :controller => 'test', :action => 'normal_action'
|
103
|
+
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
|
data/test/proxy_test.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/init'
|
2
|
+
|
3
|
+
class ProxyTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@controller = TestController.new
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
def @request.host; env['HTTP_X_FORWARDED_HOST'].blank? ? env['HTTP_HOST'] : env['HTTP_X_FORWARDED_HOST'].split(/,\s/).last; end
|
9
|
+
@response = ActionController::TestResponse.new
|
10
|
+
@dispatcher = ActionController::Dispatcher.new(StringIO.new)
|
11
|
+
@dispatcher.instance_variable_set('@request', @request)
|
12
|
+
ActionController::UrlWriter.default_url_options[:host] = nil
|
13
|
+
ActionController::Base.relative_url_root = nil
|
14
|
+
|
15
|
+
Proxy.replace_host_with do |request|
|
16
|
+
'replaced.com' if request.host == 'replace-me.com'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_not_replace_host
|
21
|
+
@request.env['HTTP_HOST'] = 'dont-replace-me.com'
|
22
|
+
assert_equal 'dont-replace-me.com', @request.host
|
23
|
+
Proxy.send(:before_dispatch, @dispatcher)
|
24
|
+
assert_equal 'dont-replace-me.com', @request.host
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_replace_host
|
28
|
+
@request.env['HTTP_HOST'] = 'replace-me.com'
|
29
|
+
assert_equal 'replace-me.com', @request.host
|
30
|
+
Proxy.send(:before_dispatch, @dispatcher)
|
31
|
+
assert_equal 'replaced.com', @request.host
|
32
|
+
end
|
33
|
+
|
34
|
+
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,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hybridgroup-proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.6
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sean Huber, with changes from Ron Evans
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-08 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: A gem/plugin that allows rails applications to respond to multiple domains
|
15
|
+
and proxied requests
|
16
|
+
email: shuber@huberry.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- CHANGELOG
|
22
|
+
- init.rb
|
23
|
+
- lib/proxy/action_controller/abstract_request.rb
|
24
|
+
- lib/proxy/action_controller/base.rb
|
25
|
+
- lib/proxy/action_controller/named_route_collection.rb
|
26
|
+
- lib/proxy/action_controller/url_rewriter.rb
|
27
|
+
- lib/proxy/action_view/url_helper.rb
|
28
|
+
- lib/proxy.rb
|
29
|
+
- MIT-LICENSE
|
30
|
+
- Rakefile
|
31
|
+
- README.markdown
|
32
|
+
- test/init.rb
|
33
|
+
- test/abstract_request_test.rb
|
34
|
+
- test/base_test.rb
|
35
|
+
- test/named_route_collection_test.rb
|
36
|
+
- test/proxy_test.rb
|
37
|
+
- test/url_helper_test.rb
|
38
|
+
- test/url_rewriter_test.rb
|
39
|
+
homepage: http://github.com/hybridgroup/proxy
|
40
|
+
licenses: []
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --line-numbers
|
44
|
+
- --inline-source
|
45
|
+
- --main
|
46
|
+
- README.markdown
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.8.6
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: A gem/plugin that allows rails applications to respond to multiple domains
|
67
|
+
and proxied requests
|
68
|
+
test_files:
|
69
|
+
- test/abstract_request_test.rb
|
70
|
+
- test/base_test.rb
|
71
|
+
- test/named_route_collection_test.rb
|
72
|
+
- test/proxy_test.rb
|
73
|
+
- test/url_helper_test.rb
|
74
|
+
- test/url_rewriter_test.rb
|