Как получать POST запросы только от локального хоста?
Есть такая задача:
получить POST запрос через Express
-> провести необходимые операции с данными
-> отправить их через socket.io
Загвоздка в том, что Express и socket.io должны быть на одном и том же порте, при этом запросы к экспрессу должны поступать только от localhost и не более.
Можно ли как-то это реализовать, не проверяя IP отдельно при принятии каждого запроса?
Ответы (1 шт):
Наш проект будет иметь такую структуру:
.
./package.json
./src
./src/index.js
./public
./public/index.html
Создаём проект
$ yarn init -y
Устанавливаем пакеты, которые нужны для работы:
expressдля того чтобы написать простой серверbody-parserдля того чтобы раскодировать данные, приходящие в POST-запросахsocket.ioдля работы с websocket-ами
$ yarn add express body-parser socket.io
package.json
{
"name": "html",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"socket.io": "^3.0.5"
}
}
По инструкции, опубликованной на сайте socket.io, создаём простой сервер src/index.js.
Он должен уметь:
отдавать index.html и скрипты клиентской части socket.io
принимать POST-запросы
устанавливать websocket-соединение и посылать на client-side сообщения
const http = require('http');
const path = require('path');
const { promisify } = require('util');
const express = require('express');
const bodyParser = require('body-parser');
const { Server: socketioServer } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new socketioServer(server);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//
app.use(
'/static',
express.static(process.cwd() + '/static')
);
app.get(
'/',
(req, res) => res.sendFile(path.join(process.cwd(), '/public/index.html'))
);
app.post(
'/',
async (req, res) => {
res.status(204).json();
await promisify(setTimeout)(1000 * Math.random());
io.sockets.emit('message', JSON.stringify(req.body));
}
);
//
io.on('connection', (socket) => {
console.log('a user connected');
io.sockets.emit('message', 'hello!');
});
//
const port = +(process.env.PORT || 3000);
const hostname = process.env.HOST || 'localhost';
server.listen(port, hostname, () => console.log(`Server running http://${hostname}:${port}`));
Обработчик, о котором вы спрашиваете, выглядит так:
app.post(
'/',
async (req, res) => {
res.status(204).json();
// ... выполнение каких-то действий ...
// отсылка сообщения клиенту
io.sockets.emit('message', JSON.stringify(req.body));
}
);
Создаём клиентскую страничку public/index.html на которой будет форма и показ сообщений, пришедших по websocket
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<style>
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
#input:focus { outline: none; }
#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }
#messages { list-style-type: none; margin: 0; padding: 0; font-size: 8pt; }
#messages > li { padding: 0.5rem 1rem; white-space: pre; }
#messages > li:nth-child(odd) { background: #efefef; }
</style>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
socket.on('message', (data) => {
const el = document.createElement('li');
document.getElementById('messages').prepend(el);
el.innerHTML = `${new Date().toISOString()}: ${data}`;
});
async function syncData(ev) {
ev.preventDefault();
const message = document.getElementById('input').value;
const data = { message };
try {
await fetch('/', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
} catch (err) {
alert(err.message);
}
document.getElementById('form').reset();
}
</script>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="" onsubmit="return true">
<input id="input" autocomplete="off" /><button onclick="syncData(event)">Send</button>
</form>
</body>
</html>
Запускаем приложение в консоли
$ yarn start
