From 55a4f1fc869e41aca748c63d3018f0448b1606e0 Mon Sep 17 00:00:00 2001 From: pack Date: Sun, 9 Aug 2026 10:37:07 +0000 Subject: first commit --- node_modules/router/lib/layer.js | 247 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 node_modules/router/lib/layer.js (limited to 'node_modules/router/lib/layer.js') diff --git a/node_modules/router/lib/layer.js b/node_modules/router/lib/layer.js new file mode 100644 index 0000000..6a4408f --- /dev/null +++ b/node_modules/router/lib/layer.js @@ -0,0 +1,247 @@ +/*! + * router + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2022 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +const isPromise = require('is-promise') +const pathRegexp = require('path-to-regexp') +const debug = require('debug')('router:layer') +const deprecate = require('depd')('router') + +/** + * Module variables. + * @private + */ + +const TRAILING_SLASH_REGEXP = /\/+$/ +const MATCHING_GROUP_REGEXP = /\((?:\?<(.*?)>)?(?!\?)/g + +/** + * Expose `Layer`. + */ + +module.exports = Layer + +function Layer (path, options, fn) { + if (!(this instanceof Layer)) { + return new Layer(path, options, fn) + } + + debug('new %o', path) + const opts = options || {} + + this.handle = fn + this.keys = [] + this.name = fn.name || '' + this.params = undefined + this.path = undefined + this.slash = path === '/' && opts.end === false + + function matcher (_path) { + if (_path instanceof RegExp) { + const keys = [] + let name = 0 + let m + // eslint-disable-next-line no-cond-assign + while (m = MATCHING_GROUP_REGEXP.exec(_path.source)) { + keys.push({ + name: m[1] || name++, + offset: m.index + }) + } + + return function regexpMatcher (p) { + const match = _path.exec(p) + if (!match) { + return false + } + + const params = {} + for (let i = 1; i < match.length; i++) { + const key = keys[i - 1] + const prop = key.name + const val = decodeParam(match[i]) + + if (val !== undefined) { + params[prop] = val + } + } + + return { + params, + path: match[0] + } + } + } + + return pathRegexp.match((opts.strict ? _path : loosen(_path)), { + sensitive: opts.sensitive, + end: opts.end, + trailing: !opts.strict, + decode: decodeParam + }) + } + this.matchers = Array.isArray(path) ? path.map(matcher) : [matcher(path)] +} + +/** + * Handle the error for the layer. + * + * @param {Error} error + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handleError = function handleError (error, req, res, next) { + const fn = this.handle + + if (fn.length !== 4) { + // not a standard error handler + return next(error) + } + + try { + // invoke function + const ret = fn(error, req, res, next) + + // wait for returned promise + if (isPromise(ret)) { + if (!(ret instanceof Promise)) { + deprecate('handlers that are Promise-like are deprecated, use a native Promise instead') + } + + ret.then(null, function (error) { + next(error || new Error('Rejected promise')) + }) + } + } catch (err) { + next(err) + } +} + +/** + * Handle the request for the layer. + * + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handleRequest = function handleRequest (req, res, next) { + const fn = this.handle + + if (fn.length > 3) { + // not a standard request handler + return next() + } + + try { + // invoke function + const ret = fn(req, res, next) + + // wait for returned promise + if (isPromise(ret)) { + if (!(ret instanceof Promise)) { + deprecate('handlers that are Promise-like are deprecated, use a native Promise instead') + } + + ret.then(null, function (error) { + next(error || new Error('Rejected promise')) + }) + } + } catch (err) { + next(err) + } +} + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Layer.prototype.match = function match (path) { + let match + + if (path != null) { + // fast path non-ending match for / (any path matches) + if (this.slash) { + this.params = {} + this.path = '' + return true + } + + let i = 0 + while (!match && i < this.matchers.length) { + // match the path + match = this.matchers[i](path) + i++ + } + } + + if (!match) { + this.params = undefined + this.path = undefined + return false + } + + // store values + this.params = match.params + this.path = match.path + this.keys = Object.keys(match.params) + + return true +} + +/** + * Decode param value. + * + * @param {string} val + * @return {string} + * @private + */ + +function decodeParam (val) { + if (typeof val !== 'string' || val.length === 0) { + return val + } + + try { + return decodeURIComponent(val) + } catch (err) { + if (err instanceof URIError) { + err.message = 'Failed to decode param \'' + val + '\'' + err.status = 400 + } + + throw err + } +} + +/** + * Loosens the given path for path-to-regexp matching. + */ +function loosen (path) { + if (path instanceof RegExp || path === '/') { + return path + } + + return Array.isArray(path) + ? path.map(function (p) { return loosen(p) }) + : String(path).replace(TRAILING_SLASH_REGEXP, '') +} -- cgit v1.2.3