RiserBob logoRiserBobv1.0.0
HomeDocsCLIRelease notes

Getting started

  • Introduction
  • Installation
  • Quick start
  • Project structure

Core concepts

  • Routing
  • Request
  • Responses
  • Error handling

Middleware

  • Middleware
  • Authentication
  • Logger and CORS

Data

  • Validation

Structure and tooling

  • Modules
  • CLI

Examples

  • Build a project
  • Mongoose
  • Drizzle ORM
  • Sequelize
  • JWT and cookies
  • File uploads

Packages

  • Cookies

Resources

  • Troubleshooting
  • Release notes
  • License
  • Security
  • Contributing
Core concepts

Routing

Register routes with the Sponge methods, read parameters and understand how paths are matched.

Registering routes

Register routes with the Sponge methods. Each one takes a path, a handler and any number of route-specific middleware, and returns the app so calls can be chained.

TypeScript
bob  .spongGet('/users', listUsers)  .spongPost('/users', createUser)  .spongPut('/users/:id', replaceUser)  .spongPatch('/users/:id', updateUser)  .spongDelete('/users/:id', deleteUser)
MethodHTTP verb
spongGet(path, handler, ...middleware)GET
spongPost(path, handler, ...middleware)POST
spongPut(path, handler, ...middleware)PUT
spongPatch(path, handler, ...middleware)PATCH
spongDelete(path, handler, ...middleware)DELETE
spongHead(path, handler, ...middleware)HEAD
Paths must start with /. Registering the same method and path twice throws an error, so mistakes show up at startup rather than in production.

Route parameters and query strings

TypeScript
bob.spongGet('/users/:id', async (spongReq, spongRes) => {  const { id } = spongReq.params // decoded automatically  const page = spongReq.query.get('page') // URLSearchParams   return spongRes.json({ id, page })})
With noUncheckedIndexedAccess enabled, which the starter project does, spongReq.params.id has the type string | undefined. Check it before you use it: if (!id) return spongRes.SpongBadRequest().

How paths are matched

  • A route matches when it has the same number of segments as the request path.
  • :name segments capture a value and decode it with decodeURIComponent. A malformed encoding does not match.
  • A trailing slash is ignored, so /users/ reaches the /users route.
  • Static routes win over dynamic ones, whatever the registration order. With both /users/me and /users/:id registered, a request to /users/me goes to the static route.
TypeScript
// Both routes can live side by side, in any order.bob.spongGet("/api/tasks/me", controller.findMe, auth.middleware);bob.spongGet("/api/tasks/:id", controller.findOne, auth.middleware);

Starting the server

TypeScript
bob.spongListen(4000, () => {  console.log('RiserBob is running on http://localhost:4000')})

spongListen(port = 4000, callback?) starts the server on Bun and returns it. The callback runs once the server is up.

When nothing matches

  • No route for the path: 404 Not Found.
  • The path exists but not for that method: 405 Method Not Allowed, with an Allow header listing the methods that do exist among GET, POST, PUT, PATCH and DELETE.

OPTIONS requests

The server answers every OPTIONS request itself, with 204, before routing. When the request has an Origin header the answer carries the CORS preflight headers, so a browser preflight works without you registering a route.

Because OPTIONS is handled before routing, a route registered with spongOptions is never reached through the server. Use corsMiddleware to add CORS headers to your real responses.
PreviousProject structureNextRequest

On this page

  • Registering routes
  • Route parameters and query strings
  • How paths are matched
  • Starting the server
  • When nothing matches
  • OPTIONS requests