UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

106 lines 4.52 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CacheTimes = exports.Confirmations = void 0; exports.LogMiddleware = LogMiddleware; exports.SetCache = SetCache; exports.CacheMiddleware = CacheMiddleware; exports.RateLimiter = RateLimiter; const logger_1 = __importDefault(require("../logger")); const rateLimit_1 = require("../models/rateLimit"); const config_1 = require("../services/config"); function LogObj(logOut) { logger_1.default.info(`${logOut.time} | ${logOut.ip} | ${logOut.phase} | ${logOut.took} | ${logOut.method} | ${logOut.status} | ${logOut.url} | ${logOut.openConnections} open`); } let openConnections = 0; function LogPhase(req, res, phase) { const ip = req.header('CF-Connecting-IP') || req.socket.remoteAddress || req.hostname; const logOut = { time: req.startTime ? req.startTime.toTimeString() : new Date().toTimeString(), ip: ip.padStart(22, ' '), phase: phase.padStart(8, ' '), method: req.method.padStart(6, ' '), status: '...'.padStart(5, ' '), url: `${req.baseUrl}${req.url}`, took: '...'.padStart(10, ' '), openConnections: openConnections.toString().padStart(6, ' ') }; if (req.startTime && ['END', 'CLOSED'].includes(phase)) { const endTime = new Date(); const startTime = req.startTime ? req.startTime : endTime; const totalTime = endTime.getTime() - startTime.getTime(); const totalTimeMsg = `${totalTime} ms`.padStart(10, ' '); logOut.took = totalTimeMsg.padStart(10, ' '); logOut.status = res.statusCode.toString().padStart(5, ' '); } LogObj(logOut); } function LogMiddleware() { return (req, res, next) => { req.startTime = new Date(); openConnections++; LogPhase(req, res, 'START'); res.on('finish', () => { LogPhase(req, res, 'END'); }); res.on('close', () => { openConnections--; LogPhase(req, res, 'CLOSED'); }); next(); }; } var Confirmations; (function (Confirmations) { Confirmations[Confirmations["None"] = 0] = "None"; Confirmations[Confirmations["Shallow"] = 1] = "Shallow"; Confirmations[Confirmations["Deep"] = 100] = "Deep"; })(Confirmations || (exports.Confirmations = Confirmations = {})); var CacheTimes; (function (CacheTimes) { CacheTimes[CacheTimes["None"] = 0] = "None"; CacheTimes[CacheTimes["Second"] = 1] = "Second"; CacheTimes[CacheTimes["Minute"] = 60] = "Minute"; CacheTimes[CacheTimes["Hour"] = 3600] = "Hour"; CacheTimes[CacheTimes["Day"] = 86400] = "Day"; CacheTimes[CacheTimes["Month"] = 2592000] = "Month"; CacheTimes[CacheTimes["Year"] = 31536000] = "Year"; })(CacheTimes || (exports.CacheTimes = CacheTimes = {})); function SetCache(res, serverSeconds, browserSeconds = 0) { res.setHeader('Cache-Control', `s-maxage=${serverSeconds}, max-age=${browserSeconds}`); } function CacheMiddleware(serverSeconds = CacheTimes.Second, browserSeconds = CacheTimes.None) { return (_, res, next) => { SetCache(res, serverSeconds, browserSeconds); next(); }; } function isWhiteListed(whitelist = [], ip) { return whitelist.some(listItem => ip.startsWith(listItem)); } function RateLimiter(method, perSecond, perMinute, perHour) { return async (req, res, next) => { try { const identifier = req.header('CF-Connecting-IP') || req.socket.remoteAddress || ''; const rateLimiter = config_1.Config.for('api').rateLimiter; const whitelist = rateLimiter && rateLimiter.whitelist; const isDisabled = rateLimiter && rateLimiter.disabled; if (isDisabled || isWhiteListed(whitelist, identifier)) { return next(); } let [perSecondResult, perMinuteResult, perHourResult] = await rateLimit_1.RateLimitStorage.incrementAndCheck(identifier, method); if (perSecondResult.value.count > perSecond || perMinuteResult.value.count > perMinute || perHourResult.value.count > perHour) { return res.status(429).send('Rate Limited'); } } catch (err) { logger_1.default.error('Rate Limiter failed'); } return next(); }; } //# sourceMappingURL=middleware.js.map