Зарегистрируйтесь, чтобы продолжить обучение

Запрос JS: HTTP Server

После того, как клиент делает запрос на сервер, 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);

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»