Routing
In general, routing in Lunatic is as follows:
app.<method>([path], <handler>)
where
<method>
— HTTP method of the request in lowercase (get
,post
, …)[path]
— optional request path (/
,/api
, …)<handler>
— handler for the specified route
Request handler
Request handler (of type RequestHandler
) is a
function that accepts 3 arguments:
req
:Request
— incoming HTTP requestres
:Response
— server HTTP responsenext
:NextHandler
— next handler, which can be called and awaited inside the current one
Examples
Here are simple routing examples. You can add them in your first application:
import { LunaticServer } from '@shelepuginivan/lunatic'
const app = new LunaticServer()
app.get('/', (req, res) => { res.status(200).json({ hello: 'lunatic' })})
app.post('/', (_req, res) => { res.status(200).json({ message: 'POST request' }) })
app.put('/', (_req, res) => { res.status(200).json({ message: 'PUT request' }) })
app.delete('/', (_req, res) => { res.status(200).json({ message: 'DELETE request' }) })
app.listen(8000).then(() => console.log('Server started on port 8000...'))
Arbitrary request methods
In addition to app.get
, app.post
,
etc. methods you can use app.use
to handle all request
methods.
app.use('/route', (req, res, next) => { console.log('Every method can be handled')
next() // call the next handler})
Arbitrary request paths
You can omit the path
parameter. In this case handler function receives all requests with the matching method:
// Set X-Handle-Time header on every GET request.app.get((req, res, next) => { res.setHeader('X-Handle-Time', Date.now()) next()})
Dynamic paths
Lunatic supports dynamic route paths:
*
— matches all paths (exception is the empty one which is a different endpoint).:<param>
— matches a single part of the request path...[params]
— similar to*
, but also captures all path parameters
Path parameters can be accessed with req.params
.
Below are examples:
// Handles GET /:id// e.g. /1, /b9e5e951-cc0e-4d6d-b659-a28fc7a74362 etc.app.get('/:id', (req, res) => { const id = req.params.id // get the id from req.params res.status(200).text(id)})
// Handles GET /...arr// e.g /a/b/c/d, /a, /1/2 etc.app.get('/...arr', (req, res) => { res.status(200).json(req.params.arr)})
// Handles GET /admin/*// e.g. /admin/drop_database, /admin/sudo/rm_rf// but NOT /admin, because `*` does not match the empty pathapp.get('/admin/*', (_req, res) => { res.status(501).end()})
Router
In addition to RequestHandler
(a handler
function as in examples above), request methods accepts
Router
. Router
is a class of Lunatic framework which acts
similarly as the base server (LunaticServer
).
Basically, routers implement sub-routing which can be used for application
decomposition. For example, there can be separate routers for authorization,
API, etc.
import { Router } from '@shelepuginivan/lunatic'
const myRouter = new Router()
myRouter.get('/', (_req, res) => { res.status(200).text('Hello from Router!')})
app.use('/router', router) // handle all requests to /router with the created router
Nesting is also supported:
const router = new Router()const innerRouter = new Router()
innerRouter.get('/some', (_req, res) => { res.status(200).json({ message: 'Hello from inner router' })})
router.use('/inner', innerRouter)app.use('/router', router)