be
Backend framework - app config, route dispatch, HTTP server startup, request/response helpers, logging and CORS middleware, in-memory and Redis caching.
Load with: use be
What this module does
be is a thin backend framework that wraps srv (the raw HTTP server)
with a route table, middleware chain, error handling, request parsing, and response shortcuts.
You create an app config with bene, define routes with bead/beps/etc.,
then call beru to start the server.
All registered routes and middleware are stored in the app config object. Each request is matched against the route table (exact method + path match), wrapped in error handling, and optionally logged. If no route matches, a 404 is returned.
All functions are also accessible as properties of the be object.
Quick example
use be
app = bene({
port: 3000,
middleware: [belg1(), becr1()]
})
app.rt = trl.cat(app.rt, [
bead("/", \(rq, rs, ap) beok(rs, {msg: "hello"})),
beps("/echo", \(rq, rs, ap) beok(rs, bejs(rq))),
benf1: bead("/404", \(rq, rs, ap) benf(rs))
])
beru(app)
Functions
App setup and server
bene(op) / be.bemk(op)
Creates an app config object from an options object. Reads: routes (list, default []), middleware (list, default []), error_handler (function, default been), logger (bool, default tru), port (int, default 8080), db and cache (both default nil).
beru(ap) / be.beus(ap)
Starts the HTTP server on 127.0.0.1:{port}. Registers all middleware via srv.srvus, sets the dispatch handler, logs the startup, and calls srv.srvru.
been(rq, rs, er)
The default error handler. Logs the error, sets status 500, and responds with {er: error_string} as JSON.
belg(rq)
Logs the HTTP method and path of a request using obs.obslg.
Route helpers
Each returns a route descriptor {mt, pt, hd} - method, path, and handler function.
bead(pt, hd) / be.bead(pt, hd)
GET route.
beps(pt, hd) / be.beps(pt, hd)
POST route.
bepu(pt, hd) / be.bepu(pt, hd)
PUT route.
bede(pt, hd) / be.bede(pt, hd)
DELETE route.
bepa(pt, hd) / be.bepa(pt, hd)
PATCH route.
Request helpers
bejs(rq) / be.bejs(rq)
Parses the request body as JSON. Errors with "be.js: invalid JSON: ..." if parsing fails.
bepa1(rq) / be.bepa1(rq)
Parses query parameters from the request URL (the ?key=value&... portion). Returns an object with URL-decoded keys and values.
behd(rq, nm) / be.behd(rq, nm)
Reads a request header by name via srv.srqhd.
Response helpers
beok(rs, bd) / be.beok(rs, bd)
200 OK. If bd is an object or list, responds with JSON. Otherwise responds with the string value.
becr(rs, bd) / be.becr(rs, bd)
201 Created. Same JSON/string logic as beok.
bebd(rs, er) / be.bebd(rs, er)
400 Bad Request with {er: error_string} JSON body.
beun(rs) / be.beun(rs)
401 Unauthorized - status only, no body.
beau(rs, bd) / be.beau(rs, bd)
403 Forbidden with {er: "Forbidden", dt: bd} JSON body.
benf(rs) / be.benf(rs)
404 Not Found - status only.
bese(rs, er) / be.bese(rs, er)
500 Internal Server Error with {er: error_string} JSON body.
Middleware
belg1() / be.belg1()
Returns a logging middleware function that logs the timestamp, method, and path of every request via obs.obslg, then calls next.
becr1() / be.becr1()
Returns a CORS middleware function. Sets Access-Control-Allow-Origin: *, allowed methods (GET, POST, PUT, DELETE, OPTIONS), and allowed headers (Content-Type, Authorization). Responds 200 to OPTIONS preflight requests and calls next for all others.
Caching
becne(tp, op) / be.becne(tp, op)
Creates a cache. tp is "redis" (connects to op.host, default "localhost:6379") or "memory" (stores in a plain object with per-key expiry timestamps). Errors on unknown types.
becgt(ca, ky) / be.becgt(ca, ky)
Gets a cached value by key. For Redis delegates to redis.redgt. For memory, checks the expiry timestamp and returns nil if expired.
becst(ca, ky, vl, ex) / be.becst(ca, ky, vl, ex)
Sets a value with an expiry. ex is seconds for Redis; converted to milliseconds for in-memory. For Redis delegates to redis.redst.
Database stubs
bdbne(tp, cn) / be.bdbne(tp, cn)
Creates a database config object with type and connection string. Not yet connected.
bdbco(db) / be.bdbco(db)
Returns the database config unchanged. Connection is a stub - not yet implemented.
bdbqu(db, qu, pr) / be.bdbqu(db, qu, pr)
Query stub - returns nil. Not yet implemented.
Notes
- Route matching is exact - method and full path (query string stripped) must match. There is no wildcard or parameterised routing in the current dispatch loop.
- Database functions (
bdbne,bdbco,bdbqu) are stubs and do not execute queries. - Requires
trl,txt,srv,net,jsn,obs,redis, andtim. - All functions are also accessible via the
beobject:be.bemk,be.beus,be.bead, etc.