Перейти к основному содержимому

Роутинг

Для введения в роутинг см. Базовый роутинг.

Маршруты (или роуты) определяются при помощи методов класса LunaticServer (или Router), например app.get() для GET запросов, app.post() для POST запросов и так далее. Также, вы можете использовать метод app.use() чтобы обрабатывать все методы запросов.

Эти методы принимают 2 аргумента: путь и обработчик. Путь - это путь запроса, а обработчик - функция, которая вызывается при получении запроса. Ниже приведён базовый пример роутинга:

import { LunaticServer } from '@shelepuginivan/lunatic'

const app = new LunaticServer()

app.get('/route', (req, res) => {
res.status(200).end()
})

Методы

Вы можете обрабатывать разные методы запросов по одному пути. Следующий код - это пример приложения, которое обрабатывает GET / и POST / запросы:

app.get('/route', (req, res) => {
res.status(200).json({ message: 'GET request' })
})

app.post('/route', (req, res) => {
res.status(200).json({ message: 'POST request' })
})
подсказка

Вы также можете использовать enum Status вместо чисел в качестве статуса ответа:

res.status(Status.Ok).end()

Вы можете использовать метод app.use() чтобы обрабатывать все методы запросов:

app.use('/route', (req, res, next) => {
console.log('Я не знаю, какой метод обработал...')
next() // вызов следующего обработчика
})

Пути маршрутов

Путь маршрута - это строка, определяющая, по какому пути запрос может быть сделан. Вместе с методом запроса, они определяют эндпоинт. Вот некоторые примеры путей:

// Обрабатывает GET /
app.get('/', (req, res) => {
res.status(200).text('Hello!')
})

// Обрабатывает GET /some
app.get('/some', (req, res) => {
res.status(200).json({ message: '/some' })
})

// Обрабатывает GET /api/posts
app.get('/api/posts', (req, res) => {
const posts = getPostsSomehow()
res.status(200).json(posts)
})

Путь маршрута можно вообще не указывать, в этом случае обработчик будет вызываться при каждом запросе (если совпадает метод):

app.get((_req, res, next) => {
res.setHeader('X-Handle-Time', Date.now())
next()
})

Динамические пути маршрута

Lunatic поддерживает динамическую маршрутизацию. Система динамических путей своя, и она во многом похоже на то, как работает роутер в Next.js:

  • * совпадает со всеми путями (но не с пустым путём)
  • :<имя_параметра> совпадает с одним параметром пути
  • ...<массив_параметров> совпадает с несколькими параметрами пути

Вот несколько примеров:

// Обрабатывает GET /:id
// Например /1, /b9e5e951-cc0e-4d6d-b659-a28fc7a74362 и т.д.
app.get('/:id', (req, res) => {
const id = req.params.id // получение id из req.params
res.status(200).text(id)
})

// Обрабатывает GET /...arr
// например /a/b/c/d, /a, /1/2 и т.д.
app.get('/...arr', (req, res) => {
res.status(200).json(req.params.arr)
})

// Обрабатывает GET /admin/*
// например /admin/drop_database, /admin/sudo/rm_rf
// но НЕ /admin, потому что * не совпадает с пустым путём
app.get('/admin/*', (_req, res) => {
res.status(501).end()
})

Параметры пути

Параметры пути доступны в свойстве req.params:

app.get('/docs/:topic', (req, res) => {
console.log(req.params) // Например для GET /docs/routing: { topic: 'routing' }
res.status(204).end()
})

app.get('/multiple/...parameters', (req, res) => {
console.log(req.params) // Например для GET /multiple/1/2/3/4/5: { parameters: ['1', '2', '3', '4', '5'] }
res.status(204).end()
})
примечание

Обратите внимание, что * не добавляет параметров в req.params.

Router

Помимо RequestHandler (то есть функции обработчика, как в примерах выше), методы запросов принимают Router. Router - это класс фреймворка Lunatic, который ведёт себя схожым образом с LunaticServer. По сути, LunaticServer расширяет Router дополнительным набором методов. Вы можете думать о нём как о мини-приложении, которое устанавливается внутри основного.

Вы можете использовать Router как в примере ниже:

import { Router } from '@shelepuginivan/lunatic'

const myRouter = new Router()

myRouter.get('/', (_req, res) => {
res.status(200).text('Hello from Router!')
})

app.use('/router', router) // обрабатывать все запросы на путь /router созданым роутером

В этом примере, когда сервер принимает запрос на путь /router or /router/*, myRouter обработает этот запрос.

примечание

В отличие от функции-обработчика (HandlerFunction), Router обрабатывет все запросы, начинающиеся с указаного префикса

Вы также можете использовать роутеры внутри других роутеров:

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)

Если ни один из маршрутов не совпадает с запросом, будет вызван следующий обработчик.

Роутеры позволяют разделять логику приложение так, что каждый роутер несёт ответственность за один модуль. Например, в вашем приложении может быть роутер для постов, авторизации, для API и т.д.