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

cerberus-gateway

v0.1.3

Published

Easily create a gateway to your backend with authentication, ACL, rate limiting, analytics, logging, caching, and more

Downloads

5

Readme

Cerberus

Cerberus is a library for easily creating a gateway or access point to your backend. It can handle authentication, access control logic, rate limiting, analytics, logging, caching, and performance monitoring among other things.

Once Cerberus validates a user's request or connection, it can pass the request or connection on to the rest of your backend.

Cerberus is build around frontends, plugins, transformers, and backends:

  • Frontends are responsible for handling connections from clients (see CerberusConnection), receiving requests from clients (see CerberusRequest), and sending responses to clients (see CerberusResponse).
  • Plugins can run arbitrary code in response to a CerberusRequest, a CerberusConnection, or a CerberusResponse. This can even include things like cancelling or transforming a request or response.
  • Transformers are lightweight versions of plugins. They can be used in cases where building a generalized plugin doesn't make sense.
  • Backends are responsible for passing a CerberusRequest to another system and getting a CerberusResponse.

For example, if you wanted to accept HTTP and Websocket connections, validate an HMAC signed token, rate limit requests by IP address, limit access for users who are not logged in, and finally pass on requests to another backend system, you could do this:

var c = new Cerberus();

// Add a Websocket frontend
c.addFrontend(new WSFrontend(8080));

// Add a HTTP frontend
// `location.query` is what we want to store
c.addFrontend(new HTTPFrontend(8081, false, (httpReq, location) => location.query));

// Validate that all connections contain a query parameter named "token" that is
// signed with a specific key. This is compatible with signed cookies from Express
// (https://github.com/expressjs/cookie-parser)
// When the authenticator receives a `CerberusRequest` object, it sets the `userID`
// field in the request if the token is valid
//
// The last parameter tells the authenticator to allow requests that
// don't have a signed token (instead of responding with an error).
// Unsigned requests won't have a valid `userID`
// See the HMACAuthenticator documentation for more options
//
// Tip: "s:1.qPEYVkKbyvn8uCzA6HIjhK8xxgSPswKFJuGSGmWD0iA" is a valid signed token
c.addPlugin(new HMACAuthenticator("SUPER_SECRET_HMAC_KEY", "token", false));

// Limit all calls to 10 requests per second per IP address
c.addPlugin(new RateLimit(10, 1000, () => true));

// Don't allow unauthenticated requests where "color" is set to "green"
c.on("request", function(request) {
  // userID is not set unless the connection has a signed token
  if (!request.connection.userID) {
    if (request.data["color"] == "green") {
      return "Please login to set your color to green!"
    }
  }
})

// Set the backend
// Makes a POST request to an internal host
c.setBackend(new HTTPBackend((req) => ({
    url: "https://some-internal-host:4032",
    method: "POST",
    json: {
        user: req.connection.userID,
        data: req.data["color"]
    }
})));

This means that a client can make any of the following requests successfully:

  • HTTP request to http://localhost:8081/?token=VALID_SIGNED_TOKEN&color=green
  • HTTP request to http://localhost:8081/?color=blue
  • Websocket connection to http://localhost:8080/?token=invalid
    • Message: {"color": "blue"}
    • Message: {"color": "red"}
  • Websocket connection to http://localhost:8080/?token=VALID_SIGNED_TOKEN
    • Message: {"color": "blue"}
    • Message: {"color": "green"}

But the following requests will fail:

  • HTTP request to http://localhost:8081/?token=invalid&color=green
  • Websocket connection to http://localhost:8080/?token=invalid
    • Message: {"color": "red"}
    • Message: {"color": "yellow"}
    • Message: {"color": "green"} - This request will fail
    • Message: {"color": "blue"}

See examples/acl.ts for the complete code and tests/acl.test.ts for a test that tests all the above cases.

Getting Cerberus

npm install cerberus-gateway

Using Cerberus

Frontends

Frontends can be added with Cerberus.addFrontend(frontend).

The built in frontends are

See the links above or frontends/http.ts and frontends/ws.ts for more details and usage information.

If you want to create a new frontend, implement the interface defined in frontends/frontend-interface.ts.

Plugins

Plugins can be added with Cerberus.addPlugin(plugin, eventType) where eventType is one of "connection", "request", or "response". If a plugin only handles one of these, the eventType parameter is ignored.

If a plugin contains multiple handlers, you will need to add the plugin once for every handler. For example, if a plugin needs to run during both requests and responses, you will need to add it once to the request chain and once to the response chain.

Note: The order in which plugins are added is the order in which they are executed.

var latencyMeasurement = ... // Some plugin
c.addPlugin(latencyMeasurement, "request")

// Add other plugins

c.addPlugin(latencyMeasurement, "response")

The built in plugins are

  • LatencyLogger
    • A plugin that logs the time between a request and the corresponding response.
  • HMACAuthenticator
    • A plugin that validates a HMAC signed token when a new connection is established.
  • LRUCache
    • A plugin to cache specific requests and responses in an in-memory LRU cache.
  • RedisCache
    • A plugin to cache specific requests and responses in Redis. This is useful for sharing a cache between multiple Cerberus instances.
  • RateLimit
    • A configurable rate limiter for requests based on IP address.

See the links above or the files in the plugins directory for more details and usage information.

If you want to create a new plugin, implement the interface defined in plugins/plugin-interface.ts.

Backend:

A backend can be added with Cerberus.setBackend(backend).

The built in backends are

See the links above or backends/http.ts, backends/amqp.ts, and backends/zmq.ts for more details and usage information.

If you want to create a new backend, implement the interface defined in backends/backend-interface.ts.

Transformers:

Transformers can do everything that a handler in a plugin can do. See the plugin interface definition (plugins/plugin-interface.ts) for more details and examples/acl.ts for an example.

var c = new Cerberus();
c.on('request', function(request) {
	// Do something
})

c.on('response', function(response) {
	// Do something
})

c.on('connection', function(connection) {
	// Do something
})

Examples

See the files in the examples directory. Many of these have corresponding tests in the tests directory

Tests

Run npm test

Many of the tests work by overriding the http or ws node modules with mock versions (see tests/test-utils.ts). After this, they generally import an example from the examples folder and validate that things behave like they should. See tests/acl.test.ts for a comprehensive example.

Contributing

  1. Clone this repo
  2. Make some changes
  3. Add or modify an example in the examples folder (if applicable)
  4. Write a test in the tests folder (if applicable)
  5. Run npm run prepublish to make sure everything builds, tests pass, and there are no lint errors
  6. Send a pull request!

License

Apache 2.0