Как тестировать зависящую от поддомена логику в режиме локальной разработки на NodeJS?
Допустим, https://example_institue.edu - официальный сайт какого-то университета, а https://bioengineering.example_institue.edu - официальный сайт кафедры биоинженерии этого университета. По-хорошему каждый из этих сайтов должен обслуживать отдельный сервер (хотя бы виртуальный), тем не менее я бы хотел рассмотреть случай, когда оба сайта обслуживают один сервер и одно приложение.
В данном случае в зависимости от поддомена потребуется разный роутинг. Например, https://example_institue.edu/about - это страница информации об университете в целом, а https://bioengineering.example_institue.edu/about - это страница информации о кафедре биоинженерии, поэтому если роутеру указать просто /about, то он не сможет понять, какая именно страница нужна.
В принципе, для продакшена алгоритм ясен: нужно посмотреть поле origin в заголовках запроса и в зависимости от поддомена выбрать роутинг, объявленный тем или способом. Но как отладить этот механизм в режиме локальной разработки, где origin будет http://localhost:3000/?
Чтобы Вам в ответе не приходилось писать с нуля, приведу листинг Hello world на NodeJS с HTTP-модулем:
import HTTP from "http";
const HOST = "123.4.5.6";
const PORT = 1337;
HTTP.createServer(requestListener).listen(PORT, HOST, () => {
console.log({
title: "Сервер запущен",
description: `Ожидание запросов на хост:${HOST}, порт: ${PORT}...`
});
// В реальном приложении тут будет анализ запроса и выбор роутинга
});
Прошу в данном вопросе не рекомендовать никаких фреймворков типа express, потому что в данном вопросе идёт речь о решении задачи нативными средствами.
Ответы (2 шт):
Нужно поставить порт 80, а после в файле C:\Windows\System32\drivers\etc\hosts прописать 127.0.0.1 example_institue.edu и так каждый домен с новой строчки. Таким образом можно использовать адреса для теста.
Для начала опишем сервер
server.js
const http = require('http');
const hostname = '0.0.0.0';
const port = 8000;
const server = http.createServer((req, res) => {
console.log("Request for: " + req.headers["host"]);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
package.json
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last",
"main": "server.js",
"scripts": {
"start": "node server.js"
}
}
Я запускал все в докере.
Dockerfile
FROM node:latest
WORKDIR /home/node/app
COPY source/ ./
RUN npm install
EXPOSE 8000
CMD [ "npm", "start" ]
docker-compose.yml
version: "3.7"
services:
node:
build: .
volumes:
- "./source:/home/node/app"
ports:
- "127.0.0.1:8000:8000"
tree
~/DockerProjects/NodeJS ⌚ 11:52:17
$ tree
.
├── docker-compose.yml
├── Dockerfile
└── source
├── package.json
└── server.js
1 directory, 4 files
Запускаем сервер
~/DockerProjects/NodeJS ⌚ 11:48:42
$ dc up
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Starting nodejs_node_1 ... done
Attaching to nodejs_node_1
node_1 |
node_1 | > [email protected] start
node_1 | > node server.js
node_1 |
node_1 | Server running at http://0.0.0.0:8000/
Запросы
~ ⌚ 11:48:40
$ curl -i -H "HOST: test.com" http://127.0.0.1:8000
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Mon, 19 Jul 2021 08:49:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 11
Hello World%
~ ⌚ 11:49:53
$ curl -i http://127.0.0.1:8000
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Mon, 19 Jul 2021 08:49:58 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 11
Hello World%
~ ⌚ 11:49:58
$
результат
node_1 | Server running at http://0.0.0.0:8000/
node_1 | Request for: test.com
node_1 | Request for: 127.0.0.1:8000
Думаю, все достаточно просто. Заголовок Host клиент обязан указать для HTTP протокола версии 1.1 и выше. А заголовок Origin указывается клиентом только при кросс-доменном запросе (CORS). И указывает не на тот домен К которому выполняется запрос, а на тот ОТ которого он пришел.