Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do customer/client style subdomains using Node and Express

How does one allow customers to access a SaaS using their organization name in the domain?

For example, a web app, example.com, may have 2 customers, OrgA and OrbB.

Once logged in, each customer is redirected to their site, orga.example.com / orgb.example.com.

Once the request that includes the subdomain reaches the node server, my hope is to handle the request with a single '/' route. Inside the route handler, it simply inspects the host header and treats the subdomain as a param for the organization. Something like:

app.get "/*", app.restricted, (req, res) ->
  console.log "/* hit with #{req.url} from #{req.headers.host}"
  domains = req.headers.host.split "."
  if domains
    org = domains[0]
    console.log org
    # TODO. do something with the org name (e.g. load specific org preferences)
  res.render "app/index", { layout: "app/app" }

NB. The first item in the domains array is the organization name. I am assuming that no port appears in the host header and, for now, I am not considering how to handle non-organisation sub domain names (e.g. www, blog, etc.).

The question I therefore have is more about how node/express can be configured to handle requests with varying host headers. This is generally solved in Apache using a wildcard alias or in IIS using a host header.

An Apache/Rails example is @ http://37signals.com/svn/posts/1512-how-to-do-basecamp-style-subdomains-in-rails

How can the same be achieved in node?

like image 682
mattgi Avatar asked Jan 14 '12 04:01

mattgi


1 Answers

if you dont want to use express.vhost, you can use http-proxy to achieve a more organized routing/port system

var express = require('express')
var app = express()
var fs = require('fs')

/*
Because of the way nodejitsu deals with ports, you have to put 
your proxy first, otherwise the first created webserver with an 
accessible port will be picked as the default.

As long as the port numbers here correspond with the listening 
servers below, you should be good to go. 
*/

var proxyopts = {
  router: {
    // dev
    'one.localhost': '127.0.0.1:3000',
    'two.localhost': '127.0.0.1:5000',
    // production
    'one.domain.in': '127.0.0.1:3000',
    'two.domain.in': '127.0.0.1:4000',

  }
}

var proxy = require('http-proxy')
  .createServer(proxyopts) // out port
  // port 4000 becomes the only 'entry point' for the other apps on different ports 
  .listen(4000); // in port


var one = express()
  .get('/', function(req, res) {
   var hostport = req.headers.host
   res.end(hostport)
 })
 .listen(3000)


var two = express()
  .get('/', function(req, res) {
    res.end('I AM APP FIVE THOUSAND')
  })
  .listen(5000)
like image 122
bhurlow Avatar answered Oct 21 '22 14:10

bhurlow