Skip to content

Repository files navigation

ResourceMachine

HTTP decision machine for API gateways and microservices — Node.js port of Webmachine

npm version


HTTP is not just if (req.method === 'GET'). A production API has to get dozens of things right: content negotiation, conditional requests, ETags, caching headers, authorization, correct 4xx/5xx codes for every edge case. Most frameworks leave all of that to you, and most implementations get it quietly wrong.

ResourceMachine implements the full Webmachine v3 HTTP decision diagram — roughly 40 decision points that correctly model HTTP semantics. You describe your resource; the machine handles the protocol.

Who it's for

ResourceMachine is designed for engineers building API gateways and microservices — backends where HTTP correctness matters and separation of concerns reduces bugs. It is not a web application framework and does not try to be.

If your service needs to:

  • Return different representations based on Accept headers
  • Respect If-None-Match / If-Modified-Since for cache validation
  • Handle PUT / DELETE / PATCH with correct precondition checking
  • Enforce authorization and permission rules per endpoint
  • Do all of the above correctly, every time, without repeating yourself

…ResourceMachine handles the HTTP layer so you handle the business logic.

How it works

You define a Resource class per endpoint. Override only the methods relevant to that endpoint — everything else falls back to safe HTTP defaults. The decision machine instantiates your class per request and walks the diagram, calling your methods at the right moment.

import{createServer,Resource}from"resource-machine";classArticleResourceextendsResource{privatearticle: Article|null=null;// Which HTTP methods are allowed?overrideasyncallowedMethods(){return["GET","HEAD","PUT","DELETE"];}// Does this resource exist? Fetch it once, cache on `this`.overrideasyncresourceExists(){this.article=awaitdb.find(this.req.params.id);returnthis.article!==null;}// Serve it — article already fetched above, no second DB call.overrideasynccontentTypesProvided(){return{"application/json": ()=>JSON.stringify(this.article),};}// Accept a PUT body.overrideasynccontentTypesAccepted(){return{"application/json": async()=>{constbody=JSON.parse((awaitthis.req.getBody()).toString());this.article=awaitdb.update(this.req.params.id,body);returntrue;},};}}constserver=createServer({name: "articles-api"});server.addRoute("/articles/:id",ArticleResource);awaitserver.listen(3000);

The machine takes care of: 404 when resourceExists() is false, 405 for disallowed methods, 406 when no content type matches, 412 on failed preconditions, 304 for unmodified resources — all without you touching a status code.

Requirements

  • Node.js 22.0.0 or later
  • TypeScript (optional but strongly recommended)

Installation

npm install resource-machine

Documentation

Full documentation at jongretar.github.io/ResourceMachine.

Examples are in examples/.

License

MIT — Copyright © 2026 Jón Grétar Borgþórsson

About

Node.JS implementation of the Erlang WebMachine resource framework

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages