obelisk-lambda v0.1.4
Όbelisk λ
A powerful request router for "monolithic" Lambdas.
Obelisk is powered by find-my-way - used by Fastify and Restify. Obelisk adopts route-matching from find-my-way and provides a more Lambda-like interface for handlers.
Install
Make sure you actually want a "fat function", then:
npm i obelisk-lambdaRequires Node.js v18+ (v16 works, but isn't recommended).
Usage
lambda.js:
import { ObeliskRouter } from "obelisk-lambda";
const router = new ObeliskRouter();
router.on(
"GET",
"/things/near/:lat-:lng/radius/:r",
async ({ params, store, searchParams }) => {
const { lat, long, r } = params
// use coordinates and r (radius) to find the thing
return {
statusCode: 200,
headers: { "content-type": "application/json" },
body: JSON.stringify({ params, store, searchParams }),
};
},
);
export const handler = router.mount();A more elaborate router can be found in ./example/src/http/any-catchall/router.mjs
Deployment
The deploy target is an AWS Lambda behind a v2 HTTP API Gateway1.
These sort of HTTP Lambdas can easily deployed with Architect -- see ./example for a sample Arc project2.
1 v1 REST API Gateways are not supported. Read about API Gateway v2 Lambda integration.
2 Obelisk is not currently compatible with Arc's Node.js helper library: @architect/functions. Specifically the http() and http.async() methods.
API
Constructor
Create a new Obelisk router.
defaultRoute is optional
Similar to find-my-way, you can specify a default handler that will be invoked when no route is matched or a matched route does not return.
function defaultRoute ({ event, context, params, searchParams, store }) {
// event and context are always available
// params, searchParams, and store are only available if a route was matched
console.log("defaultRoute", event.rawPath);
return {
statusCode: 404,
headers: { "content-type": "text/plain; charset=utf8" },
body: "not found.",
};
}
const router = new ObeliskRouter({ defaultRoute });Instance Methods
on(method, path, [options], handler, [store])
Add a route to a router instance. See find-my-way's docs on method and path.
Note that handler functions are quite different from find-my-way. See Handlers API below.
router.on("GET", "/things/:id", ({ params }) => {
const { id } = params;
return {
statusCode: 200,
headers: { "content-type": "application/json" },
body: JSON.stringify({ thingId: id }),
};
});options are optional.
on() tries to maintain find-my-way's method signature.
The optional store is not managed in the same way as find-my-way and will likely change in the future.
mount()
Create a Lambda handler function from the Obelisk router.
prettyPrint()
Calls the internal router's prettyPrint method to return an ASCII diagram of known routes.
Instance Properties
These are mostly used internally and likely not helpful to developers at runtime. They are exposed for debugging purposes.
defaultRoute
The original defaultRoute passed into the constructor.
handlers
A Map of registered routes keyed by the value returned when registering a route.
router
The internal FindMyWay router instance.
Note: provided route handlers are not actually registered with router.router and are managed in router.handlers.
Handlers API
Payload
event API Gateway 2.0 Event
Reference: Working with AWS Lambda proxy integrations for HTTP APIs
context Lambda Context
Reference: AWS Lambda context object in Node.js
params FindMyWay parsed path params
router.on(
"GET",
"/things/near/:lat-:lng/radius/:r",
async ({ params }) => {
const { lat, lng, r } = params;
const thing = await things.geoFind({ lat, lng }, r);
return {
statusCode: 200,
headers: { "content-type": "application/json" },
body: JSON.stringify({ thing }),
};
},
);searchParams FindMyWay's parsed search params
router.on("GET", "/search", async ({ searchParams }) => {
const { q } = searchParams
// GET /search?rating=5&sale=true
// q == { rating: '5', sale: 'true' }
const results = await things.search({ query: q })
return {
statusCode: 200,
headers: { "content-type": "text/html; charset=utf8" },
body: renderSearchResults(results),
};
});store FindMyWay store
The store is currently passed through but not entirely functional as in find-my-way.
FAQ
- IMO ordered arguments are a bummer
resisn't as simple asreturning data- a payload with many keys means Obelisk can easily attach AWS-provided data
function (req, res) {} has, and will continue, to serve long-lived Node processes well, but structured payloads are more ergonomic for evented "cloud functions".
Decode the base64 body on the event. Assuming the body was sent as x-www-form-urlencoded (HTML forms are):
import { parse } from "node:querystring"; // or your query string parser of choice
router.on("POST", "/form", ({ event }) => {
// `event` is an APIGatewayProxyEventV2
const data = Buffer.from(event.body, "base64").toString("utf8");
const decoded = parse(data);
// ...If the original request doesn't match a route, defaultRoute is invoked with only the event and context objects.
In find-my-way it is used to persist data when the route is registered and/or between handlers. This feature is only partially implemented in Obelisk.