После того, как клиент делает запрос на сервер, node.js
формирует объект
request
и передает его в наш обработчик. Request
является инстансом
IncomingMessage
и содержит всю возможную информацию о соединении.
Нас интересует только небольшая часть этих данных.
// http://localhost:4000/search?q=php
console.log(request);
{
url: '/search?q=php',
method: 'GET',
headers: {
host: 'localhost:4000',
connection: 'close',
},
/* ... */
}
Важно упомянуть, что все заголовки в объекте headers
представлены в нижнем регистре,
причём не важно, в каком виде они были посланы на сервер. Это сильно упрощает
дальнейшую работу с заголовками. Если некоторые заголовки повторяются, их значения
будут перезаписаны или объединены в строчки разделённые точкой запятой, в зависимости
от заголовка. В некоторых случаях это может быть нежелательным, поэтому всегда
можно получить сырые заголовки, используя объект rawHeaders
.
С одной стороны видно, что здесь есть все параметры запроса, с другой – есть маленькие
неудобства. Выражаются они в том, что http
не предоставляет возможность
получить query params
в виде объекта js.
Для этого мы можем создать объект URL
и воспользоваться его свойством searchParams
.
const url = new URL(request.url, `http://${request.headers.host}`);
const q = url.searchParams.get('q');
console.log(q); // => 'php'
Существует и другой способ работы с сервером ноды:
const server = http.createServer();
server.on('request', (request, response) => {
// the same kind of magic happens here!
});
server.listen(port);
Как и многое другое в node.js
, сервер является EventEmitter
. Событие request
соответствует входящему запросу.
Request EventEmitter
Объект Request
так же является EventEmitter
. Изучим подробнее генерируемые
им события.
end
Событие end
генерируется в тот момент, когда запрос целиком получен. Обычно
обработчик именно на это событие содержит логику обработки запроса.
request.on('end', () => {
const message = 'Welcome to The Phonebook';
response.end(message);
});
error
В случае ошибок это будет событие error
. Если это событие не будет прослушано,
то возникшая ошибка превращается в исключение, что приведёт к падению программы.
Таким образом, будет хорошей практикой всегда слушать это событие и, как минимум,
логгировать его, а еще лучше отвечать вызывающей стороне правильным кодом ошибки.
request.on('error', err => {
// This prints the error message and stack trace to `stderr`.
console.error(err.stack);
})
data
Событие, которое вызывается при получении данных. Будет рассматриваться в соответствующем уроке.
В случае, если данные не принимаются и это событие не слушается, необходимо обязательно делать
вызов метода resume
на объекте request
, иначе запрос не начнёт обрабатываться.
request.resume();
Response
В общем виде запись ответа в response
выглядит так:
response.write('hello world');
response.end();
или так:
response.end('hello world');
То есть в зависимости от ситуации можно передавать данные либо сразу в end
,
либо, если они большие, отдавать порциями через write
.
По умолчанию код ответа всегда 200
. Конечно, не каждому запросу гарантируется
такой ответ, в некоторых случаях нужно отправлять совсем другой код. Самый
простой способ сделать это - напрямую поменять свойство statusCode
.
response.statusCode = 404; // Tell the client that the resource wasn't found.
Установка заголовков делается уже через специальный метод:
response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');
Важно не забывать установить все заголовки до того, как начнёт отправляться тело.
Это логично, ведь заголовки в http
идут перед телом, а поменять порядок после
отправки уже нельзя.
Всё вместе
import http from 'http';
http.createServer((request, response) => {
request.on('error', err => {
// Обрабатываем ошибки
console.error(err);
}).on('end', () => {
response.on('error', err => {
// Обрабатываем ошибки
console.error(err);
});
// Устанавливаем код ответа
response.statusCode = 200;
// Устанавливаем заголовки
response.setHeader('Content-Type', 'application/json');
const message = 'Welcome to The Phonebook';
// Устанавливаем данные в ответе
response.write(message);
// Завершаем соединение
response.end();
});
request.resume(); // !!!
}).listen(8080);
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты