• Stars
    star
    100
  • Rank 339,629 (Top 7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 16 years ago
  • Updated over 13 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Allows rails applications to respond to multiple hosts/domains and proxied requests

Proxy

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.

The original session domain, default host, and relative url root will be restored after each request.

Requires actionpack >= 2.0.0

Installation

script/plugin install git://github.com/shuber/proxy.git
OR
gem install proxy

Usage

Proxied Requests

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:

http://client.example.com/orders

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:

http://clientdomain.com/orders

This plugin will automatically detect this forwarded host and set the session domain and default host (for url generation) accordingly.

Proxied Requests with Custom URIs

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:

http://clientdomain.com/neworders

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.

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:

ActionController::AbstractRequest.forwarded_uri_header_name = 'SOME_CUSTOM_HEADER_NAME'

You can add that line in environment.rb or an initializer.

Relative Url Root Proxy Setup

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:

RewriteRule ^neworders(.*) http://client.example.com/orders$1 [P,QSA,L,E=originalUri:%{REQUEST_URI}]
RequestHeader append X_FORWARDED_URI %{originalUri}e e=originalUri

Multiple Domains

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 so you can route based on subdomains like:

ActionController::Routing::Routes.draw do |map|
  # this routing controller has a before_filter callback that looks up a site by subdomain
  map.public_page '*path', :controller => 'routing', :conditions => { :subdomain => /^[^\.]+$/ }

  map.with_options :conditions => { :subdomain => nil } do |admin|
    admin.resource :account, :controller => 'account'
    admin.resources :sites
    ...
  end
end

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:

# config/initializers/proxy.rb
    
Proxy.replace_host_with do |request|
  "#{Site.find_by_domain(request.host).try(:subdomain) || '-INVALID-'}.yourcmsapp.com" unless request.host =~ /(\.|^)yourcmsapp.com$/i
end

Let's examine what this block is doing:

  • 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...
  • It checks if a site exists with a domain that matches the current request's host.
  • If a site does exist, a new host is returned using the site's subdomain with your app domain and everything renders fine, otherwise...
  • 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-

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.

Contact

Problems, comments, and suggestions all welcome: [email protected]

More Repositories

1

curl

A basic CURL wrapper for PHP
PHP
448
star
2

sortable

Allows you to sort ActiveRecord items in multiple lists with multiple scopes
Ruby
147
star
3

vim-promiscuous

Instant context switching using git and vim sessions.
Vim Script
73
star
4

queryable_array

Provides a simplified DSL allowing arrays of objects to be searched by their attributes
Ruby
70
star
5

subdomain_account

A rails plugin that handles subdomain accounts
Ruby
59
star
6

postgres-twitter

Experimental build of a simple "twitter" app in Postgres
PLpgSQL
57
star
7

validates_as_hostname_label

Checks for valid hostname labels (i.e. subdomains)
Ruby
49
star
8

svnignore

git style ignores with subversion
Ruby
45
star
9

interface

Implementable interfaces in ruby
Ruby
31
star
10

event_calendar

Generates html event calendars with ruby
Ruby
30
star
11

authorization

authorization for rails
Ruby
26
star
12

hattr_accessor

Allows you to define attr_accessors that reference members of a hash
Ruby
26
star
13

variables

`Variable` objects for class and instance variables
Ruby
22
star
14

abstract_class

Abstract classes in Ruby
Ruby
20
star
15

eigenclass

Eigenclasses (metaclasses) in Ruby
Ruby
17
star
16

owners

Take ownership of your code
Ruby
16
star
17

defined

Calls Module#defined after a ruby class or module is (re)defined
Ruby
15
star
18

monolith

Monolithic git repository generator
Ruby
13
star
19

sub_diff

Inspect the changes of your `String#sub` and `String#gsub` replacements
Ruby
13
star
20

phuby

A port of ruby 2.0 to native php 5.4+
PHP
11
star
21

authentication

authentication for rails
Ruby
10
star
22

tmux-git

Display git information in your tmux status line
Shell
9
star
23

kalimba

JavaScript
8
star
24

restful_rails

An extendable PHP library to communicate with RESTful rails applications
PHP
5
star
25

nestable

Allows you to nest ActiveRecord records with various strategies like tree, set, path, etc.
Ruby
4
star
26

shuber.github.com

CSS
3
star
27

cache

A simple php caching library with swappable backends
PHP
3
star
28

woot

Scrapes woot.com sites with ruby
Ruby
3
star
29

pg_brainfuck

plpgsql brainfuck implementation
2
star
30

sudoku

Solves traditional square Sudoku puzzles
Ruby
2
star
31

gitserver

node gitserver
CoffeeScript
2
star
32

respond_to_missing

Defines Object#respond_to_missing? and patches Object#respond_to?
Ruby
2
star
33

goldberg

messing around with game physics in rubygame
Ruby
1
star
34

weeports

A tiny reporting application for php >= 5.3
PHP
1
star
35

jquery-favicons

Adds favicons to links
JavaScript
1
star
36

philt

PHP
1
star
37

myspace-google_analytics

Adds Google Analytics to your profile
1
star
38

smart_home

Ruby
1
star
39

taggie

The tiniest little HTML/XML parser...using regex
Ruby
1
star