Объекты request (req) и response (res) в Node.js

Модуль 4: Node.js, Next.js и Angular
4 уровень , 1 лекция
Открыта

1. Введение

Когда вы создаёте HTTP-сервер в Node.js с помощью модуля http, вы обязательно пишете нечто вроде:

const http = require('http');

const server = http.createServer((req, res) => {
    // Тут магия
});

server.listen(3000);

Вот эти самые req и res — это два объекта, которые Node.js автоматически создаёт для каждого входящего HTTP-запроса. Они играют роль «почтальонов»: один приносит вам письмо (запрос клиента), другой — отправляет ваш ответ обратно.

  • req (IncomingMessage) — объект, который содержит всю информацию о входящем запросе: URL, метод (GET, POST и т.д.), заголовки, тело запроса и прочее.
  • res (ServerResponse) — объект, с помощью которого вы формируете и отправляете ответ клиенту: указываете статус-код, заголовки, тело ответа.

Всё взаимодействие между браузером (или другим клиентом) и вашим сервером происходит через эти два объекта.

2. Объект request (req): свойства и методы

Какой тип у req?

Объект req — это экземпляр класса http.IncomingMessage. Это поток (stream), который позволяет читать данные, поступающие от клиента.

Основные свойства req

Давайте разберём самые полезные свойства, которые пригодятся в 99% случаев:

Свойство Что хранит Пример значения
req.url
URL, по которому пришёл запрос (всё после домена и порта)
/about?user=vasya
req.method
HTTP-метод запроса (GET, POST, PUT, DELETE и т.д.)
'GET'
,
'POST'
req.headers
Объект всех HTTP-заголовков запроса
{ host: 'localhost:3000', ... }
req.httpVersion
Версия HTTP-протокола
'1.1'
,
'2.0'

Пример: Выводим информацию о запросе

const http = require('http');

const server = http.createServer((req, res) => {
    console.log('URL:', req.url);
    console.log('Method:', req.method);
    console.log('Headers:', req.headers);
    res.end('OK');
});

server.listen(3000, () => {
    console.log('Server started on port 3000');
});

Запусти сервер, зайди на http://localhost:3000/about?user=vasya — и посмотри в консоль!

req.url: путь и параметры

req.url — это строка, которая содержит путь и query-параметры. Например, если клиент запросил http://localhost:3000/about?user=vasya, то req.url будет /about?user=vasya.

Чтобы разбирать URL на части (путь, параметры), удобно использовать встроенный класс URL:

const url = new URL(req.url, `http://${req.headers.host}`);
console.log(url.pathname); // '/about'
console.log(url.searchParams.get('user')); // 'vasya'

req.method: что хочет клиент?

HTTP-метод показывает, что именно хочет сделать клиент: получить данные (GET), отправить (POST), изменить (PUT), удалить (DELETE), и так далее. Обычно для одного и того же пути (/users) сервер может по-разному реагировать на разные методы.

if (req.method === 'GET') {
    // Вернуть данные
} else if (req.method === 'POST') {
    // Принять новые данные
}

req.headers: заголовки запроса

req.headers — это обычный объект JavaScript, где ключи — названия заголовков (в нижнем регистре!), а значения — строки.

console.log(req.headers['user-agent']); // Браузер клиента
console.log(req.headers['content-type']); // Тип передаваемых данных

req.body: где тело запроса?

В отличие от фреймворков типа Express, в «голом» Node.js у объекта req нет свойства body. Если клиент отправляет данные (например, через POST), их нужно читать из потока вручную:

let body = '';
req.on('data', chunk => {
    body += chunk;
});
req.on('end', () => {
    console.log('Body:', body);
    res.end('Received!');
});

Важно: Для GET-запросов тело обычно отсутствует; для POST/PUT/PATCH — может быть.

req.socket: информация о соединении

Иногда нужно узнать IP-адрес клиента или другие детали соединения:

console.log(req.socket.remoteAddress); // Например, '::1' (localhost)

3. Объект response (res): свойства и методы

Какой тип у res?

Объект res — это экземпляр класса http.ServerResponse. Это поток для записи (writeable stream), с помощью которого вы отправляете данные клиенту.

Основные методы res

Метод Для чего нужен Пример использования
res.statusCode
Установить HTTP-статус ответа (по умолчанию 200)
res.statusCode = 404;
res.setHeader()
Добавить/изменить HTTP-заголовок
res.setHeader('Content-Type', 'text/html')
res.write()
Отправить часть тела ответа (можно несколько раз)
res.write('Hello, ')
res.end()
Завершить ответ и отправить всё клиенту
res.end('world!')

Пример: Отправляем HTML-страницу

const http = require('http');

const server = http.createServer((req, res) => {
    res.statusCode = 200; // Можно не писать, если 200
    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    res.write('<h1>Hello, world!</h1>');
    res.write('<p>Привет с сервера!</p>');
    res.end(); // Завершаем ответ
});

server.listen(3000);

res.statusCode: статус ответа

HTTP-статус — это число, которое сообщает клиенту, как сервер обработал запрос. Самые частые:

  • 200 — OK (всё хорошо)
  • 404 — Not Found (не найдено)
  • 500 — Internal Server Error (что-то сломалось)

Важно: Если не указать явно, будет 200.

res.setHeader(name, value): заголовки ответа

С помощью этого метода вы управляете метаданными ответа: типом содержимого, политикой кэширования, куками и так далее.

res.setHeader('Content-Type', 'application/json');

res.write(data): отправка данных

Можно отправлять часть данных сразу, а потом ещё кусочек. Обычно, если ответ небольшой, пишут только res.end(data).

res.write('Часть 1');
res.write(' и часть 2');
res.end(' — конец!');

res.end([data]): завершение ответа

Обязательный шаг! Без вызова res.end() клиент будет ждать ответа вечно, и браузер «подвиснет».

res.end('Всё, пока!');

res.writeHead(statusCode, headers): старый способ

Можно сразу установить статус и заголовки одним методом (устаревший, но встречается):

res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not found');

4. Примеры: делаем сервер чуть умнее

Пример 1: Простой роутинг по пути

const http = require('http');

const server = http.createServer((req, res) => {
    if (req.url === '/') {
        res.setHeader('Content-Type', 'text/html');
        res.end('<h1>Главная страница</h1>');
    } else if (req.url === '/about') {
        res.setHeader('Content-Type', 'text/html');
        res.end('<h1>О нас</h1>');
    } else {
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Страница не найдена');
    }
});

server.listen(3000);

Пример 2: Отправляем JSON

const http = require('http');

const server = http.createServer((req, res) => {
    if (req.url === '/api/user') {
        res.setHeader('Content-Type', 'application/json');
        const user = { name: 'Вася', age: 30 };
        res.end(JSON.stringify(user));
    } else {
        res.statusCode = 404;
        res.end('Not found');
    }
});

server.listen(3000);

Пример 3: Читаем тело POST-запроса (например, для формы)

const http = require('http');

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.url === '/echo') {
        let body = '';
        req.on('data', chunk => {
            body += chunk;
        });
        req.on('end', () => {
            res.setHeader('Content-Type', 'text/plain');
            res.end('Вы отправили: ' + body);
        });
    } else {
        res.end('Только POST /echo!');
    }
});

server.listen(3000);

5. Типичные ошибки при работе с req и res

Ошибка №1: Не вызван res.end()

Если забыть вызвать res.end(), браузер будет ждать ответа бесконечно. Даже если вы отправили данные через res.write(), обязательно завершайте ответ.

Ошибка №2: Неправильный Content-Type

Если отправляете JSON, но забыли поставить Content-Type: application/json, браузер или клиент может не понять, что это за данные.

Ошибка №3: Множественный вызов res.end()

Вызовите res.end() только один раз! Повторный вызов приведёт к ошибке: Cannot set headers after they are sent to the client.

Ошибка №4: Чтение тела запроса без обработки событий

Если вы читаете тело запроса через req.on('data'), но не слушаете событие end, то не узнаете, когда данные пришли полностью, и ответ отправится раньше времени.

Ошибка №5: Использование req.body в чистом Node.js

В отличие от Express, в Node.js у объекта req нет свойства body по умолчанию. Его нужно собирать вручную из чанков потока.

1
Задача
Модуль 4: Node.js, Next.js и Angular, 4 уровень, 1 лекция
Недоступна
Вывод информации о запросе
Вывод информации о запросе
1
Задача
Модуль 4: Node.js, Next.js и Angular, 4 уровень, 1 лекция
Недоступна
Эхо POST-запроса с разбираемым путем
Эхо POST-запроса с разбираемым путем
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ