npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

apigateway-path-match

v0.3.0

Published

Matcher / router for API Gateway-style paths

Downloads

6

Readme

apigateway-path-match

A javascript router for AWS Lambda

Install apigateway-path-match via npm:

$ npm install apigateway-path-match

Define your routes using the set(method, path, value) function:

const PathMatcher = require('apigateway-path-match');
const router = new PathMatcher();

router.set("GET", "/foo",        "Getting foo");
router.set("GET", "/foo/{id}",   "Getting one foo");
router.set("ANY", "/foo/{any+}", "Catch-all foo");

Then lookup particular requests against your routes using the match(method, path) function:

var m;
m = router.match("GET", "/foo/123");        // m is "Getting one foo"
m = router.match("DELETE", "/foo/bar/baz"); // m is "Catch-all foo"
m = router.match("GET", "/foobar");         // m is null, because no route matched

In typical usage, you wouldn't use strings for values; you'd use route handlers. Here's how that looks like in an AWS Lambda function:

const PathMatcher = require('apigateway-path-match');
const router = new PathMatcher();

router.set("GET", "/foo", (event, context, callback) => {
    callback(null, { statusCode: 200, body: "This is foo" });
});
router.set("GET", "/bar", (event, context, callback) => {
    callback(null, { statusCode: 200, body: "This is bar" });
});
// Set more routes here...

const notFound = (event, context, callback) => {
    callback(null, { statusCode: 404, body: "Not Found" });
};

exports.handler = (event, context, callback) => {
    const routeHandler = router.match(event.httpMethod, event.path);
    if (routeHandler) {
        return routeHandler(event, context, callback);
    }

    return notFound(event, context, callback);
};

Matching Rules

Path patterns are made up of "/"-separated components. Each component can be either

  1. A literal value, e.g. "foo" or "";
  2. A wildcard, if it starts with "{" and ends with "}", e.g. "{foo}";
  3. A super-wildcard, if it starts with "{" and ends with "+}", e.g. "{foo+}".

A wildcard will match anything except "/", i.e. it will accept any value for this path component. A super-wildcard will match anything including "/", i.e. it will accept any value for the remainder of the path. Wildcard and super-wildcard are equivalent to respectively the * and ** patterns used in globbing libraries like minimatch.

It's meaningless for a path pattern to have any components following a super-wildcard. set will throw an Error if you try to create one. For example, the following path patterns are illegal:

  • /{foo+}/bar
  • /foo/{bar+}/{baz}
  • /foo/{bar+}/{baz+}

Literal matches have higher precedence than wildcard matches, which have higher precedence than super-wildcard matches. E.g.

router.set("GET", "/foo/bar/baz",  "Literal");
router.set("GET", "/foo/{id}/baz", "Wildcard");
router.set("GET", "/foo/{any+}",   "Super-wildcard");

router.match("GET", "/foo/bar/baz");  // "Literal"
router.match("GET", "/foo/123/baz");  // "Wildcard"
router.match("GET", "/foo/bar/quux"); // "Super-wildcard"

All paths must start with "/", but the leading slash is ignored (there is no literal empty string path component before it). set will throw an Error if the path pattern doesn't start with "/".

In addition to a path pattern, each route added to PathMatcher has a method. This can be any HTTP method, case-insensitive (e.g. "GET", "Post", etc). Multiple methods can be given at once in an array. As a special case, the "ANY" method acts as a fallback which matches any method. It has lower precedence than explicitly specified methods, e.g.

router.set(["GET", "PUT"], "/foo/{id}",  "Explicit method");
router.set("ANY",          "/foo/{id}",  "Catch-all method");

router.match("PUT", "/foo/123"); // "Explicit method"
router.match("POST", "/foo/123"); // "Catch-all method"

These rules are based on my understanding of how Amazon API Gateway works, based on the developer guide.

Caveats

No consistency checks. If you set the same pattern more than once, the earlier values are silently overwritten by the latest one:

router.set("GET", "/foo", "Original value");
router.match("GET", "/foo"); // "Original value"

router.set("GET", "/foo", "New value");
router.match("GET", "/foo"); // "New value"

No uniqueness guarantee. You can store any kind of value in your router; this library never checks them. Multiple patterns can point to the same value. When you perform a match, there's no way to know which pattern matched. If this information is important to you, make sure all your values are unique, such that the pattern to value mapping is one-to-one.

Ambiguity. When a match fails, this library doesn't tell you whether it's because of the path or the method. If this distinction is important to you, you can use wildcard methods to catch cases where the path matches, but the method doesn't, e.g.

var routes = [
    ["GET",  "/foo", "Get foos"],
    ["POST", "/foo", "Create a foo"],
];

for (let [method, pathPattern, value] of routes) {
    router.set(method, pathPattern, value);
    router.set("ANY", pathPattern, "Method didn't match");
}