truss/emitters/http.js
2019-03-05 19:21:09 -06:00

86 lines
2.2 KiB
JavaScript

const {createServer} = require('http');
const bodyParser = require('body-parser');
const {invokeHookReduce} = require('@truss/comm');
const {ActionEmitter} = require('./index');
const debug = require('debug')('truss:emitters:http');
const parser = bodyParser.json();
module.exports = class HttpActionEmitter extends ActionEmitter {
constructor(executors, listeners) {
super(executors, listeners);
this.server = createServer();
}
listen() {
const port = process.env.GATEWAY_PORT || 8000;
this.server.listen(port);
this.server.on('listening', () => {
debug(`listening on port ${port}...`);
})
this.server.on('request', (req, res) => { parser(req, res, () => {
const method = req.method.toLowerCase();
const url = req.url;
debug(`${method} ${url}`);
// map to action
const headers = {
...req.headers,
...{
connection: undefined,
host: undefined,
}
};
const action = {
type: undefined,
payload: {
headers: headers,
method: method,
url: url,
}
};
switch (method) {
case 'post':
// truss action
if (url.startsWith('/truss/action/')) {
action.type = url.substr('/truss/action/'.length);
}
// @truss/http-post
else {
action.type = '@truss/http-post';
}
action.payload = req.body;
break;
default:
// @truss/http-(get|delete|...)
action.type = `@truss/http-${method}`;
break;
}
this.processAction(action, res);
})});
}
onExecutorResponse(action, res, eres) {
const {payload: {headers: actionHeaders}} = action;
const {status, headers, response} = eres;
const reduced$ = invokeHookReduce(
'@truss/emitters/http', eres, actionHeaders
);
reduced$.then(({status, headers, response}) => {
res.writeHead(status || 200, headers);
res.end(response);
});
}
onNoExecutor(action, res) {
res.writeHead(501);
res.end(
'<!DOCTYPE html><html><body><h1>501 Not Implemented</h1></body></html>'
);
}
unlisten() {
this.server.close();
}
}