swint-server
Version:
Swint web server based on expressJS
282 lines (243 loc) • 6.93 kB
JavaScript
'use strict';
var swintHelper = require('swint-helper'),
defaultize = swintHelper.defaultize,
swintMiddleware = require('swint-middleware'),
swintRouter = require('swint-router'),
swintQuery = require('swint-query'),
express = require('express'),
sprintf = require('sprintf').sprintf,
http = require('http'),
https = require('https'),
fs = require('fs'),
os = require('os'),
path = require('path');
module.exports = function(options, callback) {
var that = this;
defaultize({
mode: 'local',
http: {
port: 8080,
mode: 'disabled', // 'disabled', 'enabled', 'redirect'
http2: false,
validHost: ['localhost']
},
https: {
port: 8443,
mode: 'disabled', // 'disabled', 'enabled', 'redirect'
http2: false,
validHost: ['localhost'],
certs: {
key: fs.readFileSync(path.join(__dirname, '../test_certs/localhost.key'), 'utf-8'),
cert: fs.readFileSync(path.join(__dirname, '../test_certs/localhost.crt'), 'utf-8'),
ca: []
}
},
exceptDir: path.join(__dirname, 'exception'),
exceptHandlers: [],
autorun: true,
static: {
url: '/static',
path: path.join(__dirname, 'static')
},
router: {},
orm: {},
middleware: {
loader: [],
pre: [],
post: []
}
}, options);
var addresses = this._getIPAddress();
options.http.validHost = options.http.validHost.concat(addresses);
options.https.validHost = options.https.validHost.concat(addresses);
this.options = options;
this.router = new swintRouter(this.options.router);
this.orm = new swintQuery.Manager(this.options.orm, function(err) {
if (err) {
print(4, err);
process.exit(-1);
return;
}
that._start(callback);
});
};
var _ = module.exports.prototype;
_._start = function(callback) {
this.app = express();
this.setORM();
this.validateProtocol();
this.validateHost();
this.loadMiddlewares();
this.setPreMiddlewares();
this.setStatic();
this.setApp();
this.setException();
this.setPostMiddlewares();
this.setLastMiddleware();
if (this.options.autorun) {
this.run();
}
callback(null, true);
};
_.setORM = function() {
this.app.set('orm', this.orm);
if (this.orm.hasOwnProperty('models')) {
this.app.set('models', this.orm.models);
}
};
_.validateProtocol = function() {
var that = this;
if (this.options.http.mode === 'redirect') {
this.app.all('*', function(req, res, next) {
if (req.protocol === 'http') {
res.redirect(sprintf('https://%s:%d%s', req.hostname, that.options.https.port, req.url));
} else {
next();
}
});
}
if (this.options.https.mode === 'redirect') {
this.app.all('*', function(req, res, next) {
if (req.protocol === 'https') {
res.redirect(sprintf('http://%s:%d%s', req.hostname, that.options.http.port, req.url));
} else {
next();
}
});
}
};
_.validateHost = function() {
var that = this;
this.app.get('*', function(req, res, next) {
var validHosts = that.options[req.protocol].validHost;
if (validHosts.indexOf('*')=== -1 && validHosts.indexOf(req.hostname) === -1) {
res.redirect(sprintf('%s://%s:%d%s', req.protocol, that.options[req.protocol].validHost[0], that.options[req.protocol].port, req.url));
} else {
next();
}
});
};
_.loadMiddlewares = function() {
var middlewares = this.options.middleware.loader.map(function(l) {
return swintMiddleware.loader(l);
});
this.loadedMiddlewares = {};
for (var i = 0; i < middlewares.length; i++) {
for (var key in middlewares[i]) {
this.loadedMiddlewares[key] = middlewares[i][key];
}
}
};
_.setPreMiddlewares = function() {
var that = this;
this.options.middleware.pre.forEach(function(m) {
if (typeof m === 'object') {
that.app.use(that.loadedMiddlewares[m.name](m.options));
} else {
if (that.loadedMiddlewares[m].length === 3) {
that.app.use(that.loadedMiddlewares[m]);
} else if (that.loadedMiddlewares[m].length <= 1) {
that.app.use(that.loadedMiddlewares[m]({}));
}
}
});
};
_.setStatic = function() {
var that = this;
if (Array.isArray(this.options.static)) {
this.options.static.forEach(function(s) {
that.app.use(s.url, express.static(s.path));
});
} else {
this.app.use(this.options.static.url, express.static(this.options.static.path));
}
};
_.setApp = function() {
this.router.load(this.loadedMiddlewares);
this.app.use(this.router.expRouter);
};
_.setException = function() {
var that = this;
this.app.all('*', function(req, res, next) {
if (req.not404 === undefined) {
res.status(404);
if (req.accepts('html')) {
res.type('html').sendFile(path.join(that.options.exceptDir, '404.html'));
} else if (req.accepts('json')) {
res.type('json').sendFile(path.join(that.options.exceptDir, '404.json'));
} else {
res.type('text').send('Swint - 404 Not found');
}
}
next();
});
this.setExceptHandlers();
this.app.use(function(err, req, res, next) {
print(4, err.stack);
res.status(500);
if (req.accepts('html')) {
res.type('html').sendFile(path.join(that.options.exceptDir, '500.html'));
} else if (req.accepts('json')) {
res.type('json').sendFile(path.join(that.options.exceptDir, '500.json'));
} else {
res.type('text').send('Swint - 500 Internal server error');
}
next();
});
};
_.setExceptHandlers = function() {
var that = this;
this.options.exceptHandlers.forEach(function(m) {
if (typeof m === 'object') {
that.app.use(that.loadedMiddlewares[m.name](m.options));
} else {
if (that.loadedMiddlewares[m].length === 4) {
that.app.use(that.loadedMiddlewares[m]);
} else {
print(4,m+ ' is not used');
}
}
});
};
_.setPostMiddlewares = function() {
var that = this;
this.options.middleware.post.forEach(function(m) {
if (typeof m === 'object') {
that.app.use(that.loadedMiddlewares[m.name](m.options));
} else {
if (that.loadedMiddlewares[m].length === 3) {
that.app.use(that.loadedMiddlewares[m]);
} else if (that.loadedMiddlewares[m].length <= 1) {
that.app.use(that.loadedMiddlewares[m]({}));
}
}
});
};
_.setLastMiddleware = function() {
this.app.use(function() { });
};
_.run = function() {
if (this.options.http.mode !== 'disabled') {
this.httpServer = http.createServer(this.app);
this.httpServer.listen(this.options.http.port);
print(2, sprintf('HTTP server listening on port %s', this.options.http.port));
}
if (this.options.https.mode !== 'disabled') {
this.httpsServer = https.createServer(this.options.https.certs, this.app);
this.httpsServer.listen(this.options.https.port);
print(2, sprintf('HTTPS server listening on port %s', this.options.https.port));
}
};
_._getIPAddress = function() {
var interfaces = os.networkInterfaces(),
addresses = [];
for (var k in interfaces) {
for (var k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family === 'IPv4' && !address.internal) {
addresses.push(address.address);
}
}
}
return addresses;
};