Роутинг на стороне сервера в NodeJS
В данной статье я покажу Вам как можно сделать простой роутинг на стороне сервера в NodeJS.
Итак, далее код сервера:
import http from 'http'
import { findRoute } from './router.js'
import url from 'url'
/**
* Обработчики запросов (Контроллеры)
*
* @type {{error404: handlers.error404, userPost: handlers.userPost, index: handlers.index, posts: handlers.posts, user: handlers.user, users: handlers.users}}
*/
const handlers = {
// главная страница
index: (req, res) => {
res.write('Index page')
},
// страница всех записей блога
posts: (req, res) => {
res.write('Post page')
},
// страница со статьей конкретного пользователя
userPost: (req, res) => {
res.write(`User ${req.params.name} wrote post ${req.params.postName}`)
},
users: (req, res) => {
res.write('Users page')
},
user: (req, res) => {
res.write(`User ${req.params.name}`)
},
error404: (req, res) => {
res.write('Error 404')
}
}
// список маршрутов
const routes = [
{ name: 'index@index', url: '/', handler: handlers.index },
{ name: 'index@userPost', url: '/user/:name/post/:postName', handler: handlers.userPost },
{ name: 'index@posts', url: '/posts', handler: handlers.posts },
{ name: 'index@users', url: '/users', handler: handlers.users },
{ name: 'index@user', url: '/user/:name', handler: handlers.user },
{ name: 'index@notfound', url: '/notfound', handler: handlers.error404 },
]
// маршрут при ошибке 404
const getNotFoundRoute = (routes) => routes.find(route => route.name === 'index@notfound')
// пишет необходимые заголовки
function writeHeaders(req, res, callback) {
res.setHeader('Content-Type', 'text/html; charset=utf8');
callback(req, res);
res.end();
}
// главная функция
function main(req, res)
{
// получаем запрошенный путь
const { pathname } = url.parse(req.url)
// ищем подходящий маршрут
const route = findRoute(pathname, routes, getNotFoundRoute(routes));
// отдаем ответ в браузер
writeHeaders(req, res, route.handler);
}
// создаем сервер по адресу http://localhost:9090
http.createServer(main).listen(9090)
Код роутера
import http from 'http';
// является ли значение числом
const isNumeric = (n) => !isNaN(n)
// преобразовываем значения параметров запроса в числа
const objectPropToNumber = (obj) => {
Object.keys(obj).forEach(key => {
if (isNumeric(obj[key])) {
obj[key] = Number(obj[key])
}
})
return obj;
}
// преобразуем URL маршрута в регулярное выражение
export const convertRouteURLToRegEx = (routeURL) => {
let _routeURL = routeURL
.replace(/:(\w+)/g,'(?<$1>\\w+)')
.replace(/\//g,'\\/')
return new RegExp(`^${_routeURL}$`)
}
/**
* Ищем маршрут
*
* @param path {string} строка запроса от пользователя
* @param routes {Array<Object>} массив всех маршрутов
* @param fallbackRoute {Object} маршрут 404
* @returns {*|number|bigint}
*/
export function findRoute(path, routes, fallbackRoute)
{
http.IncomingMessage.prototype.params = {}
const foundRoute = routes.find(route => {
const routeRegex = convertRouteURLToRegEx(route.url)
const matches = path.match(routeRegex)
//console.log('Path: ', path, '| RouteURL: ', route.url, '| RouteRegex: ', routeRegex, '| Matches: ', matches)
if( matches ) {
console.log('!!!Matched!!!', route)
// если у маршрута есть параметры, т.е. маршрут имеет такой вид
// /user/:name/post/:id, то кладем в прототип запроса (IncomingMessage) объект params
// в контроллерах сможем получать их значения вот так
// req.params.name или req.params.id
if( Object.keys(matches.groups).length > 0 )
http.IncomingMessage.prototype.params = objectPropToNumber(matches.groups);
return route
}
})
return foundRoute ? foundRoute : fallbackRoute
}
Код достаточно хорошо комментирован, но если остались вопросы - задавайте их в комментариях!
-
- Михаил Русаков
Комментарии (5):
Уважаемый Михаил! Спасибо за ваши статьи. Подскажите пожалуйста как открыть rasp.xml на javascript из папки мои документы(или вложенной в мои документы папке). Нужно для того чтобы клиент сохранял в удобную папку rasp.xml и в браузере просматривал и дополнял информацию в нем. Спасибо заранее!
Ответить
Здравствуйте! Расскажите, пожалуйста, подробнее о Вашей задаче - не очень понятно - 1) что за файл (примерное содержание), 2) почему в браузере (нужен интерфейс?), xml можно и в текстовом редакторе редактировать
Ответить
Это обычный файл расписания нужных действий. не всегда есть интернет поэтому возникла идея сбрасывать пользователям xml файл и на Javascript написать небольшое приложение для просмотра расписания и его дополнения. на php это делали fileRasp.load
Ответить
Пожалуйста, еще более подробно, желательно по пунктам, распишите, что Вы хотите. Если я правильно понял (могу ошибаться), Вам нужно браузерное приложение, которое будет позволять пользователю открывать xml файл, редактировать его, а затем сохранять. "не всегда есть интернет" - т.е. когда Интернет появляется скидывать этот файл всем остальным
Ответить
Спасибо большое за ответ. Да хочу узнать как на JS открыть файл xml, изменить его и записать. И все это в каталоге мои документы или загрузки. Заранее благодарю.
Ответить
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.