Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Запрос JS: HTTP Server

После того, как клиент делает запрос на сервер, nodejs формирует объект 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, иначе запрос не начнёт обрабатываться.

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);

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

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

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

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнения
2000+
часов теории
3200
тестов

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

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

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

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

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Node.js-разработчик
Профессия
Разработка бэкенд-компонентов веб-приложений
22 сентября 8 месяцев

Есть вопрос или хотите участвовать в обсуждении?

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

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»