Роутинг на стороне сервера в 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
}
    
    Код достаточно хорошо комментирован, но если остались вопросы - задавайте их в комментариях!
- 
					Создано 23.07.2020 11:50:05  
- 
					 Михаил Русаков Михаил Русаков
 
			 
			 
		 
				 
			 
				 
				 
				 
				
Комментарии (5):
Уважаемый Михаил! Спасибо за ваши статьи. Подскажите пожалуйста как открыть rasp.xml на javascript из папки мои документы(или вложенной в мои документы папке). Нужно для того чтобы клиент сохранял в удобную папку rasp.xml и в браузере просматривал и дополнял информацию в нем. Спасибо заранее!
Ответить
Здравствуйте! Расскажите, пожалуйста, подробнее о Вашей задаче - не очень понятно - 1) что за файл (примерное содержание), 2) почему в браузере (нужен интерфейс?), xml можно и в текстовом редакторе редактировать
Ответить
Это обычный файл расписания нужных действий. не всегда есть интернет поэтому возникла идея сбрасывать пользователям xml файл и на Javascript написать небольшое приложение для просмотра расписания и его дополнения. на php это делали fileRasp.load
Ответить
Пожалуйста, еще более подробно, желательно по пунктам, распишите, что Вы хотите. Если я правильно понял (могу ошибаться), Вам нужно браузерное приложение, которое будет позволять пользователю открывать xml файл, редактировать его, а затем сохранять. "не всегда есть интернет" - т.е. когда Интернет появляется скидывать этот файл всем остальным
Ответить
Спасибо большое за ответ. Да хочу узнать как на JS открыть файл xml, изменить его и записать. И все это в каталоге мои документы или загрузки. Заранее благодарю.
Ответить
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.