UNPKG

tsunamy

Version:

A new typesript framework

229 lines (228 loc) 12.1 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var Router_1 = require("./Router"); var Log_1 = require("./Log"); var fs_1 = __importDefault(require("fs")); var https_1 = __importDefault(require("https")); var http_1 = __importDefault(require("http")); var http_status_1 = require("./http-status"); var MimeTypes = { html: 'text/html', jpeg: 'image/jpeg', jpg: 'image/jpeg', png: 'image/png', js: 'text/javascript', css: 'text/css' }; var Server = /** @class */ (function () { function Server() { } Server.prototype.bootstrapModule = function (module, CONFIGURATION) { if (!CONFIGURATION.locale) { CONFIGURATION.locale = 'en-US'; } function originIsAuthorized(originsAllowed, originToCheck) { if (typeof originToCheck === 'string') { return originsAllowed.includes(originToCheck); } else { for (var _i = 0, originToCheck_1 = originToCheck; _i < originToCheck_1.length; _i++) { var origin_1 = originToCheck_1[_i]; if (originsAllowed.includes(origin_1)) { return true; } } return false; } } function app(req, res) { var _this = this; var bodyChunk = []; var body; req.on('error', function (err) { console.error(err); }).on('data', function (chunk) { bodyChunk.push(chunk); }).on('end', function () { return __awaiter(_this, void 0, void 0, function () { var originsAllowed, originHeader, isAuthorized, methods, headers, methodsAllowed, headersAllowed, route, result; return __generator(this, function (_a) { switch (_a.label) { case 0: originsAllowed = CONFIGURATION.allowOrigins || []; originHeader = req.headers.origin; isAuthorized = originHeader && originIsAuthorized(originsAllowed, originHeader); if (originHeader && isAuthorized) { res.setHeader('Access-Control-Allow-Origin', originHeader); } if (!(req.method === 'OPTIONS')) return [3 /*break*/, 1]; // Safari (and potentially other browsers) need content-length 0, // for 204 or they just hang waiting for a body Log_1.Log.info('(Pre-flight request) Call : ' + req.method + ' ' + req.url); if (isAuthorized) { methods = CONFIGURATION.allowMethods || []; headers = CONFIGURATION.allowHeaders || []; methodsAllowed = 'PUT,GET,POST,DELETE' + (methods.length > 0 ? ',' + methods.toString() : ''); headersAllowed = headers.length > 0 ? headers.toString() : '*'; res.setHeader('Access-Control-Allow-Methods', methodsAllowed); res.setHeader('Access-Control-Allow-Headers', headersAllowed); res.setHeader('Content-Length', '0'); res.statusCode = http_status_1.HttpStatus.OK.getCode(); res.end(); } else { Log_1.Log.err('(Pre-flight request) Origin ' + originHeader + ' unknown'); res.statusCode = http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getCode(); res.end(); } return [3 /*break*/, 4]; case 1: body = JSON.parse(Buffer.concat(bodyChunk).toString() || '{}'); route = Router_1.Router.resolve(req.url, req.method); if (!!route.error) return [3 /*break*/, 3]; if (route.isStaticFile) { // If static files serveStaticFiles(req, res); return [2 /*return*/]; } Log_1.Log.info('Call : ' + req.method + ' ' + req.url); return [4 /*yield*/, Router_1.Router.executeRouteFunction(req, res, route.urlParam, route.queryParam, body, route.function, route.controllerInstance)]; case 2: result = _a.sent(); serveResponse(result, res); return [2 /*return*/]; case 3: backError(route, res); _a.label = 4; case 4: return [2 /*return*/]; } }); }); }); } function backError(route, res) { var error = route.error; if (error) { if (route.message) { if (typeof error === 'number') { res.statusCode = error; res.end(error + ' ' + route.message); } else { Log_1.Log.err('Status code type is incorrect'); res.statusCode = http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getCode(); Log_1.Log.info('Response Code : ' + res.statusCode); res.end(http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()); } } else { Log_1.Log.info('Response Code : ' + error); var httpStatus = http_status_1.HttpStatus.getValueOf(error); if (httpStatus) { res.statusCode = httpStatus.getCode(); res.end(httpStatus.getReasonPhrase()); } else { res.statusCode = error; res.end(error + ' Error'); } } } } function serveStaticFiles(req, res) { var urlDecoded = decodeURIComponent(req.url); if (urlDecoded === '/') { // default index.html urlDecoded = '/index.html'; } var extension = urlDecoded.substring(urlDecoded.lastIndexOf('.') + 1); if (extension) { extension = extension.toLowerCase(); } var mimeType = MimeTypes[extension]; var filename = CONFIGURATION.projectDirectory + '/public' + urlDecoded; Log_1.Log.info('Serve static files : file name : ' + filename + ' mime type ' + mimeType); var readStream = fs_1.default.createReadStream(filename); readStream.on('open', function () { res.writeHead(http_status_1.HttpStatus.OK.getCode(), mimeType); readStream.pipe(res); }); readStream.on('error', function (err) { if (err.code === 'ENOENT') { res.statusCode = http_status_1.HttpStatus.NOT_FOUND.getCode(); res.end(http_status_1.HttpStatus.NOT_FOUND.getReasonPhrase()); } else { res.statusCode = http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getCode(); res.end(http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()); } }); } /** * Fill ServerResponse value from application's returned value * * @param result route's returned value * @param res server response */ function serveResponse(result, res) { Log_1.Log.info('Server result', result); res.setHeader('Content-Type', 'application/json'); res.statusCode = result.getCode(); res.end(JSON.stringify(result.getBody())); } Log_1.Log.setLocale(CONFIGURATION); Log_1.Log.initLog(CONFIGURATION); Router_1.Router.setConfig(CONFIGURATION); if (CONFIGURATION.http) { this.currentServerHttp = http_1.default.createServer(app); this.currentServerHttp.listen(CONFIGURATION.httpPort, CONFIGURATION.hostname, function () { Log_1.Log.info("Tsunamy server running at http://" + CONFIGURATION.hostname + ":" + CONFIGURATION.httpPort + "/"); }); } if (CONFIGURATION.https) { var privatekey = fs_1.default.readFileSync(CONFIGURATION.projectDirectory + '/certificate/key.pem', 'utf-8'); var certificate = fs_1.default.readFileSync(CONFIGURATION.projectDirectory + '/certificate/certificate.pem', 'utf-8'); this.currentServerHttps = https_1.default.createServer({ key: privatekey, cert: certificate }, app); this.currentServerHttps.listen(CONFIGURATION.httpsPort, CONFIGURATION.hostname, function () { Log_1.Log.info("Tsunamy https server running at https://" + CONFIGURATION.hostname + ":" + CONFIGURATION.httpsPort + "/"); }); } Log_1.Log.blue(Log_1.Log.logoWithColor()); }; return Server; }()); exports.Server = Server;