forked from expressjs/express
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Updating to the latest path-to-regexp.
BREAKING CHANGE: Latest version of path-to-regexp no longer allows path routes like /* (use /(.*) instead), /users/id:(\\d+) (use /users/id-(\\d+) instead)
- Loading branch information
1 parent
5a3a9ef
commit 9a759c7
Showing
9 changed files
with
1,166 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
/*! | ||
* router | ||
* Copyright(c) 2013 Roman Shtylman | ||
* Copyright(c) 2014 Douglas Christopher Wilson | ||
* MIT Licensed | ||
*/ | ||
|
||
'use strict' | ||
|
||
/** | ||
* Module dependencies. | ||
* @private | ||
*/ | ||
|
||
var {pathToRegexp} = require('path-to-regexp') | ||
|
||
/** | ||
* Module variables. | ||
* @private | ||
*/ | ||
|
||
var hasOwnProperty = Object.prototype.hasOwnProperty | ||
var TRAILING_SLASH_REGEXP = /\/+$/ | ||
|
||
/** | ||
* Expose `Layer`. | ||
*/ | ||
|
||
module.exports = Layer | ||
|
||
function Layer (path, options, fn) { | ||
if (!(this instanceof Layer)) { | ||
return new Layer(path, options, fn) | ||
} | ||
|
||
var opts = options || {} | ||
|
||
this.handle = fn | ||
this.keys = [] | ||
this.name = fn.name || '<anonymous>' | ||
this.params = undefined | ||
this.path = undefined | ||
this.regexp = pathToRegexp((opts.strict ? path : loosen(path)), this.keys, opts) | ||
|
||
// set fast path flags | ||
this.regexp._slash = path === '/' && opts.end === false | ||
} | ||
|
||
/** | ||
* 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) { | ||
var fn = this.handle | ||
|
||
if (fn.length !== 4) { | ||
// not a standard error handler | ||
return next(error) | ||
} | ||
|
||
try { | ||
// invoke function | ||
var ret = fn(error, req, res, next) | ||
|
||
// wait for returned promise | ||
if (isPromise(ret)) { | ||
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) { | ||
var fn = this.handle | ||
if (fn.length > 3) { | ||
// not a standard request handler | ||
return next() | ||
} | ||
|
||
try { | ||
// invoke function | ||
var ret = fn(req, res, next) | ||
|
||
// wait for returned promise | ||
if (isPromise(ret)) { | ||
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) { | ||
var match | ||
|
||
if (path != null) { | ||
// fast path non-ending match for / (any path matches) | ||
if (this.regexp._slash) { | ||
this.params = {} | ||
this.path = '' | ||
return true | ||
} | ||
|
||
// match the path | ||
match = this.regexp.exec(path) | ||
} | ||
|
||
if (!match) { | ||
this.params = undefined | ||
this.path = undefined | ||
return false | ||
} | ||
|
||
// store values | ||
this.params = {} | ||
this.path = match[0] | ||
|
||
// iterate matches | ||
var keys = this.keys | ||
var params = this.params | ||
|
||
for (var i = 1; i < match.length; i++) { | ||
var key = keys[i - 1] | ||
var prop = key.name | ||
var val = decodeParam(match[i]) | ||
|
||
if (val !== undefined || !(hasOwnProperty.call(params, prop))) { | ||
params[prop] = val | ||
} | ||
} | ||
|
||
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 | ||
} | ||
} | ||
|
||
/** | ||
* Returns true if the val is a Promise. | ||
* | ||
* @param {*} val | ||
* @return {boolean} | ||
* @private | ||
*/ | ||
|
||
function isPromise (val) { | ||
return val && | ||
typeof val === 'object' && | ||
typeof val.then === 'function' | ||
} | ||
|
||
/** | ||
* Loosens the given path for path-to-regexp matching. | ||
*/ | ||
function loosen (path) { | ||
if (path instanceof RegExp) { | ||
return path | ||
} | ||
|
||
return Array.isArray(path) | ||
? path.map(function (p) { return loosen(p) }) | ||
: String(path).replace(TRAILING_SLASH_REGEXP, '') | ||
} |
Oops, something went wrong.