Routing

Sequoia supports the use of app.use() as some other frameworks by default, but the core idea of this library is to use Routers. Only use app.use() if it's impossible to achieve what you want with Routers

Router usage

Router class provides a set of methods like GET, POST, PUT, PATCH, DELETE, CONNECT, HEAD and OPTIONS (which are actually named so because of the HTTP methods they handle) and 2 more: all (to handle any request on the specified route) and static (to host static files)

Basic router

All Router methods (except static) have 2 required parameters to create a route: path and ...middlewares:

  • path parameter specifies the path that the user has to navigate to in order to execute the middleware
  • ...middlewares specifies what middlewares to run on this route. It can be only 1 function or many functions, depends on your needs

To create a route simply use this construction:

const router = new Router()

router.GET('/', () => new HTTPResponse('Hello world'))

This router will display the text Hello world when you make a request to the root page (/)

Router methods

All Router methods also support chaining like so:

const router = new Router()

router
    .GET('/resource', () => new HTTPResponse('Get resource'))
    .PUT('/resource', () => new HTTPResponse('Update resource'))
    .DELETE('/resource', () => new HTTPResponse('Delete resource'))

A handler which was specified by the GET method will only be executed when the user makes a GET request. A PUT handler will be executed on PUT request and so on.

Put it all together

To connect the Router to the app use useRouter method:

import { Application, Router, HTTPResponse } from 'jsr:@sequoia/sequoia'

const app = new Application()
const router = new Router()

router.GET('/user-agent', (ctx) => new HTTPResponse(ctx.request.headers.get('User-Agent')))

app.useRouter(router)
await app.listen({ port: 8080 })

Customizing Router

The Router constructor has 1 parameter: RouterOptions:

interface RouterOptions {
    headers?: Headers
    status?: HTTPStatus | Status
    type?: string
}

These options are used to set the default HTTPResponse properties

For example if you want to set the default Header for every response, you can do this:

const defaultHeaders = new Headers()
defaultHeaders.set('X-Server', 'Sequoia')
const router = new Router({ headers: defaultHeaders })

router.GET('/', () => {
    // No need to specify the headers here, they will be set automatically
    return new HTTPResponse({
        body: 'Check the headers!'
    })
})

By using RouterOptions you can set default Response status, headers and Content-Type. But you can't use it to set the default body property though

Advanced routing

You can go beyond using strings in path and use RegExp as the path specifier. For example you can create a route which will execute the middleware whenever you make a request to the path which contains any latin letter with the length of 3 symbols:

import { Application, Router, HTTPResponse } from 'jsr:@sequoia/sequoia'

const app = new Application()
const router = new Router()

router.GET(/[a-zA-Z]{3}/, (ctx) => new HTTPResponse(`Congrats, you've reached it: ${ ctx.request.url.pathname }`))
router.GET('*', () => new HTTPResponse('Try navigating to "/abc"'))

app.useRouter(router)
await app.listen({ port: 8080 })

Also note that you can use '*' path to create a middleware that'll run on every request (Only if the request wasn't handled by the previous middlewares)

Learn more about specifying the route params here