Skip to content

pillarjs/path-to-regexp

Repository files navigation

Path-to-RegExp

Turn a path string such as /user/:name into a regular expression.

NPM version NPM downloads Build status Build coverage License

Installation

npm install path-to-regexp --save

Usage

const { pathToRegexp, match, parse, compile } = require("path-to-regexp");

// pathToRegexp(path, options?)
// match(path, options?)
// parse(path, options?)
// compile(path, options?)

Path to regexp

The pathToRegexp function returns a regular expression with keys as a property. It accepts the following arguments:

  • path A string.
  • options (optional)
    • sensitive Regexp will be case sensitive. (default: false)
    • trailing Regexp allows an optional trailing delimiter to match. (default: true)
    • end Match to the end of the string. (default: true)
    • start Match from the beginning of the string. (default: true)
    • loose Allow the delimiter to be repeated an arbitrary number of times. (default: true)
    • delimiter The default delimiter for segments, e.g. [^/] for :named parameters. (default: '/')
    • encodePath A function to encode strings before inserting into RegExp. (default: x => x, recommended: encodeurl)
const regexp = pathToRegexp("/foo/:bar");
// regexp = /^\/+foo(?:\/+([^\/]+?))(?:\/+)?$/i
// keys = [{ name: 'bar', prefix: '', suffix: '', pattern: '', modifier: '' }]

Please note: The RegExp returned by path-to-regexp is intended for ordered data (e.g. pathnames, hostnames). It can not handle arbitrarily ordered data (e.g. query strings, URL fragments, JSON, etc).

Parameters

The path argument is used to define parameters and populate keys.

Named parameters

Named parameters are defined by prefixing a colon to the parameter name (:foo). Parameter names can use any valid unicode identifier characters (similar to JavaScript).

const regexp = pathToRegexp("/:foo/:bar");
// keys = [{ name: 'foo', ... }, { name: 'bar', ... }]

regexp.exec("/test/route");
//=> [ '/test/route', 'test', 'route', index: 0 ]
Custom matching parameters

Parameters can have a custom regexp, which overrides the default match ([^/]+). For example, you can match digits or names in a path:

const regexpNumbers = pathToRegexp("/icon-:foo(\\d+).png");
// keys = [{ name: 'foo', ... }]

regexpNumbers.exec("/icon-123.png");
//=> ['/icon-123.png', '123']

regexpNumbers.exec("/icon-abc.png");
//=> null

const regexpWord = pathToRegexp("/(user|u)");
// keys = [{ name: 0, ... }]

regexpWord.exec("/u");
//=> ['/u', 'u']

regexpWord.exec("/users");
//=> null

Tip: Backslashes need to be escaped with another backslash in JavaScript strings.

Unnamed parameters

It is possible to define a parameter without a name. The name will be numerically indexed:

const regexp = pathToRegexp("/:foo/(.*)");
// keys = [{ name: 'foo', ... }, { name: '0', ... }]

regexp.exec("/test/route");
//=> [ '/test/route', 'test', 'route', index: 0 ]
Custom prefix and suffix

Parameters can be wrapped in {} to create custom prefixes or suffixes for your segment:

const regexp = pathToRegexp("{/:attr1}?{-:attr2}?{-:attr3}?");

regexp.exec("/test");
// => ['/test', 'test', undefined, undefined]

regexp.exec("/test-test");
// => ['/test', 'test', 'test', undefined]

Modifiers

Modifiers are used after parameters with custom prefixes and suffixes ({}).

Optional

Parameters can be suffixed with a question mark (?) to make the parameter optional.

const regexp = pathToRegexp("/:foo{/:bar}?");
// keys = [{ name: 'foo', ... }, { name: 'bar', prefix: '/', modifier: '?' }]

regexp.exec("/test");
//=> [ '/test', 'test', undefined, index: 0 ]

regexp.exec("/test/route");
//=> [ '/test/route', 'test', 'route', index: 0 ]
Zero or more

Parameters can be suffixed with an asterisk (*) to denote a zero or more parameter matches.

const regexp = pathToRegexp("{/:foo}*");
// keys = [{ name: 'foo', prefix: '/', modifier: '*' }]

regexp.exec("/foo");
//=> [ '/foo', "foo", index: 0 ]

regexp.exec("/bar/baz");
//=> [ '/bar/baz', 'bar/baz', index: 0 ]
One or more

Parameters can be suffixed with a plus sign (+) to denote a one or more parameter matches.

const regexp = pathToRegexp("{/:foo}+");
// keys = [{ name: 'foo', prefix: '/', modifier: '+' }]

regexp.exec("/");
//=> null

regexp.exec("/bar/baz");
//=> [ '/bar/baz', 'bar/baz', index: 0 ]
Custom separator

By default, parameters set the separator as the prefix + suffix of the token. Using ; you can modify this:

const regexp = pathToRegexp("/name{/:parts;-}+");

regexp.exec("/name");
//=> null

regexp.exec("/bar/1-2-3");
//=> [ '/name/1-2-3', '1-2-3', index: 0 ]

Wildcard

A wildcard can also be used. It is roughly equivalent to (.*).

const regexp = pathToRegexp("/*");
// keys = [{ name: '0', pattern: '[^\\/]*', separator: '/', modifier: '*' }]

regexp.exec("/");
//=> [ '/', '', index: 0 ]

regexp.exec("/bar/baz");
//=> [ '/bar/baz', 'bar/baz', index: 0 ]

Match

The match function returns a function for transforming paths into parameters:

  • path A string.
  • options (optional) The same options as pathToRegexp, plus:
    • decode Function for decoding strings for params, or false to disable entirely. (default: decodeURIComponent)
// Make sure you consistently `decode` segments.
const fn = match("/user/:id", { decode: decodeURIComponent });

fn("/user/123"); //=> { path: '/user/123', index: 0, params: { id: '123' } }
fn("/invalid"); //=> false
fn("/user/caf%C3%A9"); //=> { path: '/user/caf%C3%A9', index: 0, params: { id: 'café' } }

Note: Setting decode: false disables the "splitting" behavior of repeated parameters, which is useful if you need the exactly matched parameter back.

Compile ("Reverse" Path-To-RegExp)

The compile function will return a function for transforming parameters into a valid path:

  • path A string.
  • options (optional) Similar to pathToRegexp (delimiter, encodePath, sensitive, and loose), plus:
    • validate When false the function can produce an invalid (unmatched) path. (default: true)
    • encode Function for encoding input strings for output into the path, or false to disable entirely. (default: encodeURIComponent)
const toPath = compile("/user/:id");

toPath({ id: 123 }); //=> "/user/123"
toPath({ id: "café" }); //=> "/user/caf%C3%A9"
toPath({ id: ":/" }); //=> "/user/%3A%2F"

// When disabling `encode`, you need to make sure inputs are encoded correctly. No arrays are accepted.
const toPathRaw = compile("/user/:id", { encode: false });

toPathRaw({ id: "%3A%2F" }); //=> "/user/%3A%2F"
toPathRaw({ id: ":/" }); //=> "/user/:/", throws when `validate: false` is not set.

const toPathRepeated = compile("{/:segment}+");

toPathRepeated({ segment: ["foo"] }); //=> "/foo"
toPathRepeated({ segment: ["a", "b", "c"] }); //=> "/a/b/c"

const toPathRegexp = compile("/user/:id(\\d+)");

toPathRegexp({ id: "123" }); //=> "/user/123"

Developers

  • If you are rewriting paths with match and compiler, consider using encode: false and decode: false to keep raw paths passed around.
  • To ensure matches work on paths containing characters usually encoded, consider using encodeurl for encodePath.
  • If matches are intended to be exact, you need to set loose: false, trailing: false, and sensitive: true.

Parse

A parse function is available and returns TokenData, the set of tokens and other metadata parsed from the input string. TokenData is can passed directly into pathToRegexp, match, and compile. It accepts only two options, delimiter and encodePath, which makes those options redundant in the above methods.

Tokens

The tokens returned by TokenData is an array of strings or keys, represented as objects, with the following properties:

  • name The name of the token
  • prefix (optional) The prefix string for the segment (e.g. "/")
  • suffix (optional) The suffix string for the segment (e.g. "")
  • pattern (optional) The pattern defined to match this token
  • modifier (optional) The modifier character used for the segment (e.g. ?)
  • separator (optional) The string used to separate repeated parameters

Custom path

In some applications, you may not be able to use the path-to-regexp syntax (e.g. file-based routing), but you can still use this library for match, compile, and pathToRegexp by building your own TokenData instance. For example:

import { TokenData, match } from "path-to-regexp";

const tokens = ["/", { name: "foo" }];
const path = new TokenData(tokens, "/");
const fn = match(path);

fn("/test"); //=> { path: '/test', index: 0, params: { foo: 'test' } }

Errors

An effort has been made to ensure ambiguous paths from previous releases throw an error. This means you might be seeing an error when things worked before.

Unexpected ?, *, or +

In previous major versions / and . were used as implicit prefixes of parameters. So /:key? was implicitly {/:key}?. For example:

  • /:key?{/:key}? or /:key*{/:key}* or /:key+{/:key}+
  • .:key?{.:key}? or .:key*{.:key}* or .:key+{.:key}+
  • :key?{:key}? or :key*{:key}* or :key+{:key}+

Unexpected !, @, ,, or ;

These characters have been reserved for future use.

Express <= 4.x

Path-To-RegExp breaks compatibility with Express <= 4.x in the following ways:

  • The only part of the string that is a regex is within ().
    • In Express.js 4.x, everything was passed as-is after a simple replacement, so you could write /[a-z]+ to match /test.
  • The ? optional character must be used after {}.
  • Some characters have new meaning or have been reserved ({}?*+@!;).
  • The parameter name now supports all unicode identifier characters, previously it was only [a-z0-9].

License

MIT