Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
 *  Vhost multiple JSGI apps. Optionally set a default app, and change the root
 *  (`scriptName`) of an app.
 *
 *      require('jsgi-vhoster').middleware( {
 *        "site1.co.uk": jsgi_app,
 *        "site2.co.uk": { app: jsgi_app, default: true }
 *      } )
 *
 *  Keys are the host names to vhost on. The values must be either a function,
 *  or an object with at least an `app` key. The full list of keys understood
 *  is:
 *
 *  - app (`Function`): the JSGI app to run on this host.
 *  - default (`Boolean`): the default vhost if no host header is present, or
 *    if it doesn't match anything
 *  - scriptName (`String`): script name at which to root the app rather than
 *    the default behaviour of `/`
 **/
exports.middleware = function vhoster( sites ) {
  var def,
      explicit_default_set = false;

  // Normalize and process sites.
  for ( var i in sites ) {
    if (typeof sites[ i ] == "function")
      sites[ i ] = { app: sites[ i ] }

    // No default yet - default to taking the first item
    if ( !def ) {
      def = i;   
      if ( sites[ i ].default ) explicit_default_set = true;
    }
    else if ( sites[ i ].default ) {
      if ( explicit_default_set )
        throw new Error("Explicit default already set to " + def);
      def = i;
      explicit_default_set = true;
    }

    if ( "scriptName" in sites ) {
      sites.scriptName = sites.scriptName.replace( /\/$/, '' );
    }
  }

  var res_404 = {
    status: 404,
    headers: { "content-type": "text/html" },
    body: [ "<h1>404 Not Found</h1>" ]
  }

  return function( req ) {

    var conf,
        host = "host" in req.headers
             ? req.headers.host.replace( /:\d+$/, '')
             : req.host;

    if ( host in sites )
      conf = sites[ host ]
    else if ( def ) {
      conf = sites[ def ];
      host = def;
    }
    else
      return res_404;

    // App has requested to live under a non '/' root.
    // TODO: might want some way of specifying multiple apps under a single
    //       host. I don't need it now though.
    if ( conf.scriptName ) {
      var path = req.scriptName + req.pathInfo;
      if ( path.indexOf(conf.scriptName + "/") != 0 && path != conf.scriptName )
        // No match - 404!
        return res_404;

      req.scriptName = conf.scriptName;
      req.pathInfo = path.substr( conf.scriptName.length );
    }

    // Aaand finally, run the app
    return conf.app( req );
  }
}