Как передать объект req клиента с сервера Node в маршрут Express через запрос Axios?

Вопрос или проблема

Я создал сервер WebSocket (с использованием пакета ws), который принимает сообщения от пользователя. Когда сообщение отправляется, оно поступает напрямую на сервер, который обрабатывает его следующим образом:

const WSS = new WebSocketServer({noServer: true});

WebServer.on('upgrade', async (req, socket, head) => {
// оригинальный 'req' содержит данные, необходимые для аутентификации
try {
       await authenticateUser(req.headers); // Содержит JWT токен
    } catch (error) {
           console.log(`onupgrade ошибка: ${error}`)
           socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
           socket.destroy();
           return;
        }

  WSS.on('connection', (ws, req) => {

     ws.on('message', async (data, isBinary) => {

     if(data.sentevent === 'Delivered') { 
     // Выполнить запрос axios, но необходимо прикрепить объект req из выше
     axios.post(`/api/v1/messagetracker`,{
       messageid: 1234
     });
     }
  })

  });
});

Маршрут Express /api/v1/messagetracker использует промежуточное ПО для аутентификации пользователя следующим образом:

ExpressRouter.post('/api/v1/messagetracker',
    Middlewares.authenticateUser,
    async function (req, res, next) {
    ...
});

authenticateUser просто декодирует JWT токен:

async function authenticateUser(req, res, next) {
    try {
        req.UserDetails = await getUserData(req);
    } catch (error) {
        return res.status(error.code).json(error);
    }
    next();
}

Если маршрут был POST от клиента, тогда req существует с куками, которые содержат JWT токен. Однако, когда запрос поступает с сервера node, очевидно, что JWT токенов нет.

Поэтому мне нужно передать req, который был отправлен на сервер node (через соединение websocket) от клиента в маршрут Express.

Есть ли способ достичь этого?

Ответ или решение

Для того чтобы передать объект запроса req, полученный на сервере WebSocket, в маршруты Express с помощью Axios, вам нужно учитывать несколько моментов. Поскольку WebSocket и HTTP — это разные протоколы, вам необходимо будет вручную передать необходимые данные, такие как JWT токен, в Axios запросе. Ваша текущая структура позволяет выполнить эту задачу с некоторыми изменениями.

Вот шаги, которые необходимо выполнить для реализации этого:

  1. Извлечение токена из заголовков WebSocket-запроса:
    Вам нужно будет извлечь JWT токен из заголовков req в обработчике on('upgrade').

  2. Передача токена в Axios запрос:
    После того как у вас есть токен, вы можете передать его в заголовках вашего Axios запроса к Express маршруту.

Вот пример того, как это можно реализовать в вашем коде:

const WSS = new WebSocketServer({ noServer: true });

WebServer.on('upgrade', async (req, socket, head) => {
    try {
        await authenticateUser(req.headers); // Проверка пользователя
    } catch (error) {
        console.log(`onupgrade error: ${error}`)
        socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
        socket.destroy();
        return;
    }

    WSS.on('connection', (ws, req) => {
        ws.on('message', async (data, isBinary) => {
            if (data.sentevent === 'Delivered') {
                // Извлекаем JWT токен из заголовка
                const token = req.headers['authorization']?.split(' ')[1];

                // Выполняем запрос с Axios, передавая токен в заголовках
                try {
                    const response = await axios.post('/api/v1/messagetracker', {
                        messageid: 1234
                    }, {
                        headers: {
                            'Authorization': `Bearer ${token}` // Передача токена
                        }
                    });
                    console.log('Response from Express:', response.data);
                } catch (axiosError) {
                    console.error('Error making Axios request:', axiosError.response?.data);
                }
            }
        });
    });
});

Объяснение кода:

  1. Извлечение токена:

    • Используйте const token = req.headers['authorization']?.split(' ')[1]; для извлечения токена из заголовка Authorization. Это будет работать, если токен передается в формате Bearer <token>.
  2. Axios запрос:

    • При выполнении запроса к вашему маршруту '/api/v1/messagetracker', передайте токен в заголовках, чтобы маршрут authenticateUser мог его распознать.
  3. Обработка ошибок:

    • Добавьте обработку ошибок для Axios запроса, чтобы отлавливать возможные проблемы, возникающие при выполнении запроса.

Заключение:

Теперь, когда ваш сервер WebSocket получает событие "Delivered", он может выполнить запрос к вашему маршруту Express, передавая необходимую информацию для аутентификации. Это решение позволяет сохранить целостность логики аутентификации, предоставляет пользователю доступ к необходимым данным и обеспечивает безопасное взаимодействие между WebSocket и Express.

Если у вас возникнут дополнительные вопросы или потребуется дальнейшая помощь, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...