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 routerNesting 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)