Closed kaesar closed 5 years ago
This is maybe helpful for you. It's a compatibility class that exposes an Express like interface. You can use the "serverCompat" variable to replace the express app.
const ServerCompat = require('./compat'),
serverCompat = new ServerCompat({
http: { allowHTTP1: true, key: /* KEY */, cert: /* CERT */ },
env: 'dev'
});
"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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const restana = require('restana'), url = require('url'), https = require('https'), http2 = require('http2');
;
class ServerCompat {
constructor(config = {
server: {},
http: {
key: null,
cert: null
},
useHttp2: true,
env: 'prod'
}) {
this.config = config;
this._router = {
stack: []
};
this.disabledHeaders = [];
this.type = 'restana';
this.locals = {};
this.httpServer = this.createHttpServer(config.useHttp2, config.http);
this.server = restana(Object.assign({ ignoreTrailingSlash: true, server: this.httpServer }, config.server));
this.server.use((...args) => {
args[1].redirect = (url) => {
args[1].send('', 301, {
Location: encodeURI(url)
});
};
args[1].json = (data, statusCode) => {
args[1].setHeader('Content-Type', 'application/json');
args[1].send(data, statusCode || args[1].statusCode || 200);
};
args[1].set = (key, value) => {
args[1].setHeader(key, value);
return args[1];
};
args[1].status = (statusCode) => {
try {
args[1].statusCode = statusCode;
}
catch (e) {
console.error(e);
}
return args[1];
};
args[1].cookie = (...params) => {
console.info('Set Cookie', ...params);
};
args[0].get = (header) => {
return args[0].headers[header] || args[0].headers[header.toLowerCase()];
};
args[0].query = args[0].query || {};
args[1].on('response', e => {
if (e.code >= 400) {
console.error(e);
}
});
args[2]();
});
}
isDev() {
return this.config.env == 'dev';
}
get Router() {
return this;
}
getRouter() {
return this.server;
}
getServer() {
return this.server;
}
getHttpServer() {
return this.httpServer;
}
createHttpServer(useHttp2 = true, options) {
if (useHttp2) {
console.info('###### HTTP 2 ######');
return http2.createSecureServer(Object.assign({}, options, { settings: { enablePush: true } }));
}
else {
return https.createServer(options);
}
}
manipulateHeadersMiddleware() {
const disableHeadersMiddleware = (req, res, next) => {
for (let key of this.disabledHeaders) {
try {
res.removeHeader(key);
}
catch (e) { }
}
next();
};
return disableHeadersMiddleware;
}
listen(port) {
return __awaiter(this, void 0, void 0, function* () {
console.info('Registering routes & listen');
this.use(this.manipulateHeadersMiddleware());
let server = yield this.server.start(port);
console.info('------------------------------------------------');
console.info(`Server is running on http://0.0.0.0:${port}`);
console.info('------------------------------------------------');
});
}
compatHandler(method, url, ...params) {
try {
params = params.flat();
let handler = params.pop();
this.server[method.toLowerCase()](url, handler, {}, [...params]);
}
catch (e) {
console.error(e);
}
}
get(url, ...params) {
this.compatHandler('GET', url, ...params);
}
post(url, ...params) {
this.compatHandler('POST', url, ...params);
}
options(url, ...params) {
this.compatHandler('OPTIONS', url, ...params);
}
put(url, ...params) {
this.compatHandler('PUT', url, ...params);
}
head(url, ...params) {
this.compatHandler('HEAD', url, ...params);
}
delete(url, ...params) {
this.compatHandler('DELETE', url, ...params);
}
patch(url, ...params) {
this.compatHandler('PATCH', url, ...params);
}
all(url, ...params) {
this.get(url, ...params);
this.post(url, ...params);
this.options(url, ...params);
this.put(url, ...params);
this.head(url, ...params);
this.delete(url, ...params);
this.patch(url, ...params);
}
use(...params) {
try {
if (params.length == 1) {
this.setMiddleware(params[0]);
}
else {
this.setPathMiddleware(...params);
}
}
catch (e) {
console.error(e);
}
}
setMiddleware(middleware) {
if (this.isDev()) {
console.info(middleware.name);
}
if (middleware && typeof (middleware) == 'function') {
this.server.use((...args) => {
try {
middleware(...args);
}
catch (e) {
console.error(middleware.name, e);
args[2]();
}
});
}
else {
console.info('*** Undefined middleware ***');
}
}
setPathMiddleware(...params) {
params = params.flat();
const path = params.shift();
console.info('Creating middleware for path: ', path);
for (let i = 0; i < params.length; i++) {
if (params[i] && typeof (params[i]) == 'function') {
this.setMiddleware((req, res, next) => {
try {
let parsedUrl = url.parse(req.url);
if (parsedUrl.pathname == path) {
return params[i](req, res, next);
}
else {
next();
}
}
catch (e) {
console.error(e);
next();
}
});
}
}
}
disable(key) {
this.disabledHeaders.push(key);
}
enable(key) {
console.info(`Can't enable ${key}`);
}
set(key, value) {
console.info('Nothing to do here with ', key, ' => ', value);
}
}
module.exports = ServerCompat;
Thank you, I think it will work and I will be able to continue, only it can be nice within restana
. So this could be closed if it's not necessary for restana
.
I think that the idea behind restana is to keep it minimal in order to be really fast, and it works really great. But is something for @jkyberneees :)
Hi guys, thanks for your input here. @sarriaroman you are right, this feature is not supported either by the routers or by restana itself. We can seat an adapter on top, as you propose. If this can be part of restana project? I think so. Let's follow up here again...
Thanks for collaborating.
Hi @kaesar, I was wondering if route level middlewares is a feature that satisfies your requirements: Can you please have a look at: https://github.com/jkyberneees/ana#route-level-middlewares Here you actually can "provide multiple callback functions" to handle your request.
Thanks
Yeah, it could be. Just that for migrating is for routes in a simpler style, something like: app.get('/cool', fn1, fn2, fn3)
. I unknown the impact for restana
, so I leave it to your discretion if you find it interesting to facilitate a migration from express.
Hi @kaesar , JFYI: https://github.com/jkyberneees/ana/pull/20 Landing in 2.8.0 ;)
Regards
That's great news. Thanks a lot.
I was wondering if
restana
(orfind-my-way
, or other) could provide multiple callback functions to handle a request, like route handlers in express. This is the main impact that I have for migrating torestana
.restana
is great, well thought, thanks.