http-listener.js 5.98 KB
const MODULE_NAME = 'HTTP-LISTENER';

const express = require('express');
const ipfilter = require('express-ipfilter').IpFilter;
const removeAccents = require('remove-accents');
const uniqid = require('uniqid');

const config = require('komodo-sdk/config');
const logger = require('tektrans-logger');

const commandHandler = require('./command-handler');
const messagesArchive = require('./messages-archive');

const app = express();
const port = (config && config.listener && config.listener.http
    && config.listener.http.port && config.listener.http.port
) || 32979;

/**
 * Handler utama.
 *
 * @param  {object} req - Express request object
 * @param  {object} req.query - Express query string object
 * @param  {string} [req.query.partner] - Partner (pengirim atau penerima)
 * @param  {string} [req.query.from] - Pengirim, OBSOLETED: gunakan parameter partner
 * @param  {string} [req.query.from_raw] - Pengirim tanpa suffix (raw), OBSOLETED by partner_raw
 * @param  {string} [req.query.to] - Tujuan, jika is_outgoing, OBSOLETED: gunakan parameter partner
 * @param  {string} req.query.msg - Isi pesan
 * @param  {string} req.query.origin - Nama origin
 * @param  {string} [req.query.origin_label] - Nama origin untuk ditulis di histori pesan
 * @param  {string} [req.query.do_not_forward_to_core] - Apakah teruskan pesan ke CORE
 * @param  {string} [req.query.is_outgoing] - Apakah pesan keluar
 * @param  {object} res - Express response object
 */
function mainHandler(req, res) {
    if (!req.body) req.body = {};

    const { xid } = res.locals;

    logger.verbose(`${MODULE_NAME} 72AFD326: Got a request`, {
        xid,
        query: req.query,
        body: req.body,
    });

    if (
        (!req.body.partner && !req.query.partner)
        && (
            (!req.query.is_outgoing && !req.body.is_outgoing && !req.query.from && !req.body.from)
            || ((req.query.is_outgoing || req.body.is_outgoing) && !req.query.to && !req.body.to)
        )
    ) {
        logger.warn(`${MODULE_NAME} D254B7B454DB: Undefined parameter partner or from or to`, {
            xid,
            partner: req.body.partner || req.query.partner,
            is_outgoing: req.body.is_outgoing || req.query.is_outgoing,
            from: req.body.from || req.query.from,
            to: req.body.to || req.query.to,
        });
        res.end('ERROR. Undefined parameter: partner or from or to');
        return;
    }

    // message cleansing
    const msg = removeAccents(req.query.msg || req.body.msg || '')
        .replace(/[\u{0080}-\u{FFFF}]/gu, '')
        .trim();

    if (!msg) {
        logger.warn(`${MODULE_NAME} #92996A497D12: Undefined parameter msg`, {
            xid,
        });

        if (config.do_not_reply_warning_on_empty_message) {
            res.end('OK');
        } else {
            res.end(`ERROR. Undefined parameter: msg. XID: ${xid}`);
        }

        return;
    }

    logger.verbose(
        `${MODULE_NAME} 1E9D2388: Saving message history`,
        {
            xid,
            direction: req.body.is_outgoing || req.query.is_outgoing ? 'outgoing' : 'incoming',
            transport: req.body.origin_transport || req.query.origin_transport,
            partner: req.body.partner || req.query.partner || req.body.from || req.query.from
                || req.body.to || req.query.to,
            msg,
        },
    );

    messagesArchive.insert(
        xid,
        {
            origin_label: req.body.origin_label || req.query.origin_label
                || req.body.origin || req.query.origin,
            origin_transport: req.body.origin_transport || req.query.origin_transport,
            partner: req.body.partner_raw || req.query.partner_raw
                || req.body.from_raw || req.query.from_raw
                || req.body.from || req.query.from
                || req.body.to || req.query.to || req.body.partner || req.query.partner,
            msg,
        },
        (req.body.is_outgoing || req.query.is_outgoing) ? messagesArchive.DIRECTION_OUTGOING
            : messagesArchive.DIRECTION_INCOMING,
    );

    if (
        req.body.do_not_forward_to_core || req.query.do_not_forward_to_core
        || req.body.is_outgoing || req.query.is_outgoing
    ) {
        logger.verbose('Ignoring message', {
            xid,
            from: req.body.from || req.query.from,
            msg,
            do_not_forward_to_core: req.body.do_not_forward_to_core
                || req.query.do_not_forward_to_core,
        });

        res.end('OK');
        return;
    }

    if (!req.query.report_port && !req.body.report_port) {
        res.end('ERROR. Undefined parameter: report_port');
        return;
    }

    const params = {
        origin: req.body.origin || req.query.origin || 'MESSAGING',
        origin_transport: req.body.origin_transport || req.query.origin_transport,
        report_ip: req.body.report_ip || req.query.report_ip || req.ip,
        report_port: req.body.report_port || req.query.report_port,
        from: req.body.partner || req.query.partner || req.body.from || req.query.from,
        msg,
    };

    commandHandler(msg, params, (err, coreResponseObject, responseParams) => {
        if (err) {
            res.end(`ERROR. ${err.message || err}`);
        } else if (coreResponseObject) {
            res.json(coreResponseObject);
        } else {
            res.end(responseParams.body);
        }
    });
}

if (config.ip_whitelist && config.ip_whitelist.length) {
    app.use(ipfilter(config.ip_whitelist, { mode: 'allow', log: false }));
}

app.use((req, res, next) => {
    const xid = uniqid();
    res.locals.xid = xid;

    logger.verbose(`${MODULE_NAME} 83DF8231: Got a request`, {
        xid,
        ip: req.ip,
        method: req.method,
        requestContentType: req.get('content-type'),
        url: req.url,
    });

    next();
});

app.get('/', mainHandler);
app.post(
    '/',
    express.urlencoded({ extended: true }),
    express.json(),
    mainHandler,
);

app.listen(port, () => {
    logger.info('HTTP-LISTENER: started', {
        port, app_env: app.get('env'),
    });
});