Reputation: 2516
I am trying to setup my Nodejs/Express hosting server to have multiple applications (Sails.js app type) running on my VPS but I got this error :
/srv/data/web/vhosts/default/node_modules/vhost/index.js:78
throw new TypeError('argument server is unsupported')
^
TypeError: argument server is unsupported
at createHandle (/srv/data/web/vhosts/default/node_modules/vhost/index.js:78:9)
at vhost (/srv/data/web/vhosts/default/node_modules/vhost/index.js:39:16)
at Object.<anonymous> (/srv/data/web/vhosts/default/server.js:46:9)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
Of course I previously installed all my dependencies.
My Nodejs/Express base configuration for multiple apps is good because it works fine with this express vhosts example configuration:
https://github.com/loicsaintroch/express-vhosts
So here my nodejs server app structure:
.../vhosts/default/server.js
package.json
/app1
/app.js
/app2
/app.js
/app3
/app.js
And here my server.js file based on this previous github example:
// Module dependencies
var express = require('express');
var vhost = require('vhost');
var app = express();
// vhosts
app
.use(vhost('app1.com', require('./app1/app.js')))
.listen(8080);
And the package.json file:
{
"name": "default",
"private": true,
"version": "0.0.1",
"description": "Default git repository for some web applications.",
"dependencies": {
"express": "^4.2.0",
"vhost": "^2.0.0",
"forever": "^0.11.1",
"static-favicon": "^1.0.0",
"ejs": "^1.0.0",
"morgan": "^1.0.0",
"cookie-parser": "^1.0.1",
"body-parser": "^1.0.0",
"debug": "^0.7.4"
},
"scripts": {
"start": "forever start server.js --prod",
"debug": "node debug server.js"
},
"main": "server.js"
}
Error come from vhost npm package:
/**
* Create handle to server.
*
* @param {function|Server} server
* @return {function}
* @api private
*/
function createHandle(server){
if (typeof server === 'function') {
// callable servers are the handle
return server
} else if (typeof server.emit === 'function') {
// emit request event on server
return function handle(req, res) {
server.emit('request', req, res)
}
}
throw new TypeError('argument server is unsupported')
}
OK here precisely I think vhost package has a problem with the app.js response from sails.js framework. Here the app.js file content from my Sails.js app:
/**
* app.js
*
* Use `app.js` to run your app without `sails lift`.
* To start the server, run: `node app.js`.
*
* This is handy in situations where the sails CLI is not relevant or useful.
*
* For example:
* => `node app.js`
* => `forever start app.js`
* => `node debug app.js`
* => `modulus deploy`
* => `heroku scale`
*
*
* The same command-line arguments are supported, e.g.:
* `node app.js --silent --port=80 --prod`
*/
// Ensure a "sails" can be located:
(function() {
var sails;
try {
sails = require('sails');
} catch (e) {
console.error('To run an app using `node app.js`, you usually need to have a version of `sails` installed in the same directory as your app.');
console.error('To do that, run `npm install sails`');
console.error('');
console.error('Alternatively, if you have sails installed globally (i.e. you did `npm install -g sails`), you can use `sails lift`.');
console.error('When you run `sails lift`, your app will still use a local `./node_modules/sails` dependency if it exists,');
console.error('but if it doesn\'t, the app will run with the global sails instead!');
return;
}
// Try to get `rc` dependency
var rc;
try {
rc = require('rc');
} catch (e0) {
try {
rc = require('sails/node_modules/rc');
} catch (e1) {
console.error('Could not find dependency: `rc`.');
console.error('Your `.sailsrc` file(s) will be ignored.');
console.error('To resolve this, run:');
console.error('npm install rc --save');
rc = function () { return {}; };
}
}
// Start server
sails.lift(rc('sails'));
})();
==============================================
UPDATE: FULL SOLUTION EXAMPLE
As a synthesis of the great answer I wrote a complete case study available here
https://github.com/migswd/express-sails-vhosts
==============================================
Upvotes: 4
Views: 1896
Reputation: 24948
The problem here is that you're trying to shoehorn an example meant for Express apps to work with Sails apps.
If you look at the app.js files from the example vhost apps, they all use module.exports
to return an Express app instance. The app.js from the Sails app you posted clearly does no such thing; it doesn't export anything at all. Furthermore, that file is calling sails.lift
, which starts its own server listening on port 1337.
A little elbow grease can get this to work. Instead of lifting the Sails app, you can use sails.load
which does everything except start listening on a port. This is an asynchronous method, so it'll require a reworking of your server.js as well.
The Sails app.js files become:
var sails = require('sails');
module.exports = function(cb) {
process.chdir(__dirname);
sails.load(cb);
};
Every running sails
instance exposes its underlying Express app as .hooks.http.app
, so in your server.js, use async or something similar to load all of the Sails apps, then hook them up with vhost
:
// Module dependencies
var express = require('express');
var vhost = require('vhost');
var app = express();
var async = require('async');
async.auto({
app1: require('./app1/app.js'),
app2: require('./app2/app.js'),
app3: require('./app3/app.js')
}, function doneLoadingApps(err, apps) {
app
.use(vhost('app1.io', apps.app1.hooks.http.app))
.use(vhost('app2.io', apps.app2.hooks.http.app))
.use(vhost('app3.io', apps.app3.hooks.http.app))
// Mix in a vanilla Express app as well
.use(vhost('app4.io', require('./app4/app.js')))
.listen(8080);
});
Upvotes: 3