Вопрос или проблема
Я создал сервер 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 запросе. Ваша текущая структура позволяет выполнить эту задачу с некоторыми изменениями.
Вот шаги, которые необходимо выполнить для реализации этого:
-
Извлечение токена из заголовков WebSocket-запроса:
Вам нужно будет извлечь JWT токен из заголовковreq
в обработчикеon('upgrade')
. -
Передача токена в 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);
}
}
});
});
});
Объяснение кода:
-
Извлечение токена:
- Используйте
const token = req.headers['authorization']?.split(' ')[1];
для извлечения токена из заголовкаAuthorization
. Это будет работать, если токен передается в форматеBearer <token>
.
- Используйте
-
Axios запрос:
- При выполнении запроса к вашему маршруту
'/api/v1/messagetracker'
, передайте токен в заголовках, чтобы маршрутauthenticateUser
мог его распознать.
- При выполнении запроса к вашему маршруту
-
Обработка ошибок:
- Добавьте обработку ошибок для Axios запроса, чтобы отлавливать возможные проблемы, возникающие при выполнении запроса.
Заключение:
Теперь, когда ваш сервер WebSocket получает событие "Delivered", он может выполнить запрос к вашему маршруту Express, передавая необходимую информацию для аутентификации. Это решение позволяет сохранить целостность логики аутентификации, предоставляет пользователю доступ к необходимым данным и обеспечивает безопасное взаимодействие между WebSocket и Express.
Если у вас возникнут дополнительные вопросы или потребуется дальнейшая помощь, не стесняйтесь спрашивать!