Code Monkey home page Code Monkey logo

path-parser's Introduction

npm version Build Status

path-parser

A small library to parse and build paths. It can be used to partially or fully test paths against a defined pattern.

Partial testing allows to determine if a given path starts with the defined pattern. It is used by route-node

import { Path } from 'path-parser'
// or
const { Path } = require('path-parser')

const path = new Path('/users/:id')

// Matching
path.test('/users/00123')
// {
//  id: "00123"
// }

// Partial testing: does the provided path
// starts with the defined pattern?
path.partialTest('/users/00123/orders')
// {
//  id: "00123"
// }
path.partialTest('/profile/00123/orders')
// null

// Building
path.build({ id: '00123' })
// => "/users/00123"

Without new:

const path = Path.createPath('/users/:id')

Defining parameters

  • :param: for URL parameters
  • ;param: for matrix parameters
  • *splat: for parameters spanning over multiple segments. Handle with care
  • ?param1&param2 or ?:param1&:param2: for query parameters. Colons : are optional.

Parameter constraints

For URL parameters and matrix parameters, you can add a constraint in the form of a regular expression. Note that back slashes have to be escaped.

  • :param<\\d+> will match numbers only for parameter param
  • ;id<[a-fA-F0-9]{8} will match 8 characters hexadecimal strings for parameter id

Constraints are also applied when building paths, unless specified otherwise (set option flag ignoreConstraints to true).

// Path.build(params, opts)
var Path = new Path('/users/:id<d+>')

path.build({ id: 'not-a-number' }) // => Will throw an error
path.build({ id: '123' }) // => '/users/123'

API

Constructor

A path instance can be created two ways:

  • new Path(path: string, opts?: object): object
  • Path.create(path: string, opts?: object): object

Options available are:

  • 'queryParams': options for query parameters
  • 'urlParamsEncoding, to specify how URL parameters are encoded and decoded:
    • 'default':encodeURIComponentanddecodeURIComponentare used but some characters to encode and decode URL parameters, but some characters are preserved when encoding (sub-delimiters:+,:,',!,,,;,'*'`).
    • 'uriComponent': use encodeURIComponent and decodeURIComponent for encoding and decoding URL parameters.
    • 'uri': use encodeURI and `decodeURI for encoding amd decoding URL parameters.
    • 'none': no encoding or decoding is performed
    • 'legacy': the approach for version 5.x and below (not recoomended)

path.test(path: string, opts?: object): object | null;

Test if the provided path matches the defined path template. Options available are:

  • 'caseSensitive': whether matching should be case sensitive or not (default to false)
  • 'strictTrailingSlash': whether or not it should strictly match trailing slashes (default to false)

path.partialTest(path: string, opts?: object): object | null;

Test if the provided path is partially matched (starts with) the defined path template. Options available are:

  • 'caseSensitive': whether matching should be case sensitive or not (default to false)
  • 'delimited': whether or not a partial match should only be successful if it reaches a delimiter (/, ?, . and ;). Default to true.
  • 'queryParams': to overwrite query parameter options (see above)
  • 'urlParamsEncoding: to overwrite URL param encoding and decoding option (see above)

path.build(params?: object, opts?: object): string;

Builds the defined path template with the provided parameters

  • 'caseSensitive': whether matching should be case sensitive or not (default to false)
  • 'ignoreConstraints': whether or not to ignore parameter constraints (default to false)
  • 'ignoreSearch': whether or not to build query parameters (default to false)
  • 'queryParams': to overwrite query parameter options (see above)
  • 'urlParamsEncoding: to overwrite URL param encoding and decoding option (see above)

Related modules

path-parser's People

Contributors

alextes avatar faergeek avatar niant avatar troch avatar vojtech-dobes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

path-parser's Issues

Plus not allowed in path param

With path test: ":collection/:filename"

And actual path containing a +: \foo\something+1.png

partialTest returns null

It works if I change the default in defaultOrConstrained to this: "[a-zA-Z0-9-_.~%':|\+]+" (add \+)

Is this a bug or omitted for a reason? + is a valid literal non-escaped character in a path segment.

TypeError: PathParser is not a constructor

I just upgraded from version 3.x.x to 4.2.0, and got the above error. And makes sense since, in 4.x.x, require('path-parser') returns an Object:

const PathParser = require('path-parser');

> PathParser
{ Path: { [Function: Path] createPath: [Function] },
  default: { [Function: Path] createPath: [Function] } }

So, if used in Node, const PathParser = require('path-parser').default is required. But the CHANGELOG says nothing about it.

Better type definition for `TestMatch`

Here TestMatch type is defined as really generic object | null, but if we look at the code in the urlTest method (which computes and returns the TestMatch) the right definition should be {[k: string]: string} | null (a map instead of an object).

I guess that this would be a breaking change, even if only for Typescript users, and it will lead to bumping the major version of the package.

PR very soon ;)

Double encoding or no encoding

If I pass url params object containing url encoded value, it's encoded once again, else it's not encoded at all.

What I'd like to achieve is encoding (once) a param containing a path to be used elswhere. I get %252Fap%252Fexample-func-1.html%2523%252F instead of %2Fap%2Fexample-func-1.html%23%2F.

I would like to encode value once, but it seems to be impossible now.

This is cause by this line https://github.com/troch/path-parser/blob/master/modules/Path.ts#L190

If there is no way to prevent auto encoding - I'd be happy to introduce PR with update :)

I use router5 and here is an issue I filed there: router5/router5#404

[REQ] Add constraints to query params as well

It would be very nice to have all params function the same way and be able to constrain a query param to be a specific shape. I often use this kind of functionality for a basic check of id or jwt shape.

Percent encoding support for URL path

Seems there is no support for percent encoding either unencoded or encoded e.g.

const Path = require('path-parser');
new Path('๐Ÿฆ„');
Error: Could not parse path '%F0%9F%A6%84'
    at tokenise (/Users/alextes/code/notepad/js/node_modules/path-parser/dist/cjs/path-parser.js:95:15)
    at new Path (/Users/alextes/code/notepad/js/node_modules/path-parser/dist/cjs/path-parser.js:166:23)

Since percent encoding is allowed in URLs and common in translated routes would you appreciate a PR that supports recognizing % as part of a fragment?

After V4.0.2 Path is broken

Version: [email protected], 4.0.3, 4.0.4

NOTE: it is working as expected in path-parser#4.0.1

const Path = require('path-parser');

const path = new Path('/test/:id/url');

And I am getting TypeError: Path is not a constructor.

we might need to double check 59f43c5 commit.

Thank you.

Case insensitive query parameters names

Hello everyone!

At first, thank you for that library.

Is there any way to make path-parser treat query parameters in the case-insensitive way?

import Path from 'path-parser';

const path = new Path('/users?offset&limit');
document.write(JSON.stringify(path.test('/users?limIt=15')));
document.write("<br>");
document.write(JSON.stringify(path.test('/users?limIt=15', { caseSensitive: false })));

Will write

null
null

(example)

But I want to get {limit: '15'}.
How can I do it?

Incorrect results when using regex in path

When I don't use regex it works fine but I need to restrict my root taxons so it doesn't match everything.

With regex

const pathDef = '/:taxon1<(men|women)>/:taxon2/products/:productSlug';
const pathToTest = '/men/t-shirts/products/some-tshirt-slug';

(new Path(pathDef)).test(pathToTest);
// { taxon1: 'men', taxon2: 'men', productSlug: 't-shirts' }

Without regex

const pathDef = '/:taxon1/:taxon2/products/:productSlug';
const pathToTest = '/men/t-shirts/products/some-tshirt-slug';

(new Path(pathDef)).test(pathToTest);
// { taxon1: 'men', taxon2: 't-shirts', productSlug: 'some-tshirt-slug' }

Support for curly brackets url syntax

I understand most libraries use:

/users/:id

but Swagger, the no1 lib for defining API contracts and mocking, uses:

/users/{id}

I need to parse the Swagger-style syntax.

This is a request for that support to be added.

Thanks

Path.test fails to match when query params are omitted

When query parameters are specified in the path pattern, it does not match paths that omit all query parameters

import { Path } from 'path-parser';

const path = new Path('/foo?:bar');

// Returns {bar: 1} as expected
console.log(path.test('/foo?bar=1'));

// Fails to match, returns null. I expect this to return {foo: undefined}
console.log(path.test('/foo'));

Seems like the reason this is happening is that the full path is passed into search-string for query param parsing (

const queryParams = parseQueryParams(path, options.queryParams)
). For path /foo, search-string will try to interpret /foo as a query param key, and end up returning {'/foo': null}. This causes path matching to fail, because /foo is an unexpected key

Support for `==` in parameters

Nice little library, very usefull and easy to use.

I get base64 encoded ids from my backend. They look like this: TW92aWU6MTI1OA== (btoa("Movie:1258")), the parser can't handle these == in the strings. Could this be easily fixed somehow?

Error on last release

Hey there!

Awesome work with this troch, just wanted to let you know that on the last release you've published, it breaks saying that Path is not a constructor.

Just by using const p = new Path('/api/names/:name/:number');

But somehow it says that is not a constructor.
As soon as I downgrade to another version of the package, the same code works just fine!

Allow calling without new constructor

I mean adding something like:

// allow call as function
if (!(this instanceof Path))
    return new Path(path);

I guess it comes down to personal preference, having function-style call support make using path-parser directly easier (which I am doing at the moment, having to write a bunch of new Path just seem a bit weird).

Object query parameters

Would it be possible to get object query parameter support? A common way to support this is using brackets (e.g. express and jQuery):

http://localhost/page?a[b]=10

which serializes into the query parameters: { a: { b: 10 } }. Given the library supports array query parameters, I think object query parameter support would be a natural evolution. Here's a reasonable implementation: http://api.jquery.com/jquery.param/
It would be fantastic if we could get functionality similar to:

$.param({ a: { b: 1, c: 2 }, d: [ 3, 4, { e: 5 } ] });
// "a[b]=1&a[c]=2&d[]=3&d[]=4&d[2][e]=5"

Last, I would have done this myself if possible, but the regex rules defined in the library are too strict, and are unable to match, for example, ?a[b]=10.

Able to parse plain querystring

A route like /clubs/:slug/posts?skip=0&limit=20 will cause parser to throw error. My expectation would be to leave querystring as it is.

This maybe tricky to do, would checking each query contains = be enough?

A harder case would be /clubs/:slug/posts?skip&limit=20, in this case user may expect build({ slug: 'abc', skip: 0 }) to work.

Arrays in path

I already asked on the router5 gitter room, but got no response. I think my question is at first related to path-parser.

Is it possible to match a route/url with multiple occurrences of the same param to an array?!
For example: I need to turn a url like /users?filter=foo&filter=bar into a params object which looks like {filter: ['foo', 'bar']}.

Or is there any other pattern for handling arrays without doing manual string splitting?!

Option to treat plus signs (+) as spaces

It is common to use literal plus sign in query string as a synonym of space, and many websites support this:
https://google.com?q=foo+bar.

The w3c spec says:

Within the query string, the plus sign is reserved as shorthand notation for a space. Therefore, real plus signs must be encoded. This method was used to make query URIs easier to pass in systems which did not allow spaces.

However, there is a debate whether url encoding / decoding should treat plus signs this way, see https://stackoverflow.com/questions/5450190/how-to-encode-the-plus-symbol-in-a-url.

Can path-parser (and router5) have an option to enable such encoding/decoding of plus signs?

Unexpected behavior of partialTest

I was under the impression partialTest operated a little differently. For example:

const p = new Path('/:foo/:bar');
p.partialTest('/baz') // #=> null

actual result: null
expected result: {foo: 'baz'}

Is it possible to use the API for partial URL matches? My url will sometimes have a :bar and sometimes it won't.

Hash part of an URL

Is there a way of adding the hash as a parameter (or even query parameters in the hash) and if not, should it be added as a feature?

If I include a "#" character in a route, I get the following error:

Error: Could not parse path.
    at tokenise (removed non-helpful location in compiled code)

After a short look at the code I found out that quick fix would probably be to add "#" to the list of delimiters.

Optional param

Hi,

in url-pattern documentation there is a way to specify optional parameter through path/(:id) syntax (optional segments, wildcards and escaping).

However this module, doesn't understand it, error is: Could not parse path.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.