UNPKG

moleculer-web

Version:

Official API Gateway service for Moleculer framework

159 lines (135 loc) 3.26 kB
/* * moleculer * Copyright (c) 2021 MoleculerJS (https://github.com/moleculerjs/moleculer) * MIT Licensed */ "use strict"; const _ = require("lodash"); const fresh = require("fresh"); const etag = require("etag"); const { BadRequestError, ERR_UNABLE_DECODE_PARAM } = require("./errors"); const { MoleculerError } = require("moleculer").Errors; /** * Decode URI encoded param * @param {String} param */ function decodeParam(param) { try { return decodeURIComponent(param); } catch (_) { /* istanbul ignore next */ throw new BadRequestError(ERR_UNABLE_DECODE_PARAM, { param }); } } // Remove slashes "/" from the left & right sides and remove double "//" slashes function removeTrailingSlashes(s) { if (s.startsWith("/")) s = s.slice(1); if (s.endsWith("/")) s = s.slice(0, -1); return s; //.replace(/\/\//g, "/"); } // Add slashes "/" to the left & right sides function addSlashes(s) { return (s.startsWith("/") ? "" : "/") + s + (s.endsWith("/") ? "" : "/"); } // Normalize URL path (remove multiple slashes //) function normalizePath(s) { return s.replace(/\/{2,}/g, "/"); } /** * Compose middlewares * * @param {...Function} mws */ function compose(...mws) { const self = this; return (req, res, done) => { const next = (i, err) => { if (i >= mws.length) { if (_.isFunction(done)) return done.call(self, err); /* istanbul ignore next */ return; } if (err) { // Call only error middlewares (err, req, res, next) if (mws[i].length == 4) mws[i].call(self, err, req, res, err => next(i + 1, err)); else next(i + 1, err); } else { if (mws[i].length < 4) mws[i].call(self, req, res, err => next(i + 1, err)); else next(i + 1); } }; return next(0); }; } /** * Compose middlewares and return Promise * @param {...Function} mws * @returns {Promise} */ function composeThen(req, res, ...mws) { return new Promise((resolve, reject) => { compose.call(this, ...mws)(req, res, err => { if (err) { /* istanbul ignore next */ if (err instanceof MoleculerError) return reject(err); /* istanbul ignore next */ if (err instanceof Error) return reject(new MoleculerError(err.message, err.code || err.status, err.type)); // TODO err.stack /* istanbul ignore next */ return reject(new MoleculerError(err)); } resolve(); }); }); } /** * Generate ETag from content. * * @param {any} body * @param {Boolean|String|Function?} opt * * @returns {String} */ function generateETag(body, opt) { if (_.isFunction(opt)) return opt.call(this, body); let buf = !Buffer.isBuffer(body) ? Buffer.from(body) : body; return etag(buf, (opt === true || opt === "weak") ? { weak: true } : null); } /** * Check the data freshness. * * @param {*} req * @param {*} res * * @returns {Boolean} */ function isFresh(req, res) { if ((res.statusCode >= 200 && res.statusCode < 300) || 304 === res.statusCode) { return fresh(req.headers, { "etag": res.getHeader("ETag"), "last-modified": res.getHeader("Last-Modified") }); } return false; } module.exports = { removeTrailingSlashes, addSlashes, normalizePath, decodeParam, compose, composeThen, generateETag, isFresh };