JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Отправка HTML и JSON-ответов, установка заголовков

Отправка HTML и JSON-ответов, установка заголовков

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

1. Зачем нужны разные типы ответов?

Когда вы пишете сервер на Node.js, он может общаться с клиентом (браузером или другим приложением) разными "языками". Самые популярные варианты:

  • HTML — для отображения страницы в браузере.
  • JSON — для передачи структурированных данных (например, ваше приложение на React или Angular запрашивает данные с сервера).
  • Plain text — просто текст, иногда для отладки.

Каждый из этих форматов требует, чтобы сервер правильно сообщил клиенту: "Эй, сейчас я пришлю тебе HTML/JSON/текст!" Для этого в HTTP-протоколе используются заголовки.

Что такое HTTP-заголовки?

HTTP-заголовки — это такие "метки" в начале ответа, которые говорят клиенту, что он сейчас получит. Например, если вы отправляете HTML-страницу, браузер должен знать, что это HTML, чтобы правильно её отобразить. Если вы отправляете JSON, браузер или JS-клиент должен понять: "Ага, это данные, а не страница!"

Главный заголовок для типа контента — это Content-Type.

  • Для HTML: Content-Type: text/html; charset=utf-8
  • Для JSON: Content-Type: application/json; charset=utf-8
  • Для обычного текста: Content-Type: text/plain; charset=utf-8

В Node.js вы управляете заголовками через методы объекта response (res):
- res.setHeader('Имя', 'Значение') — установить заголовок.
- res.writeHead(код, { заголовки }) — сразу установить статус и заголовки.

2. Отправка HTML-ответа

Давайте начнём с самого простого: отдаём HTML-страницу.

Пример: Hello, HTML!


const http = require('http');

const server = http.createServer((req, res) => {
  // Устанавливаем заголовок: говорим, что это HTML
  res.setHeader('Content-Type', 'text/html; charset=utf-8');

  // Можно ещё установить статус (например, 200 — OK)
  res.statusCode = 200;

  // Отправляем HTML-код
  res.end(`
    <html>
      <head>
        <title>Привет, Node!</title>
      </head>
      <body>
        <h1>Добро пожаловать на мой сервер!</h1>
        <p>Это простой HTML-ответ.</p>
      </body>
    </html>
  `);
});

server.listen(3000, () => {
  console.log('Сервер запущен на http://localhost:3000');
});

Что здесь происходит?

  • Мы явно указываем браузеру, что отправляем HTML.
  • Вызов res.end() завершает ответ и отправляет его клиенту.
  • Можно использовать любые HTML-теги. Да, даже <blink>, но только если вы хотите удивить палеонтологов.

Почему важно явно указывать Content-Type?

Если не указать Content-Type, браузер будет гадать, что вы ему прислали. Иногда угадает правильно, иногда — нет. Например, если отправить JSON без нужного заголовка, браузер может просто показать его как текст, а JS-клиент не сможет его распарсить.

3. Отправка JSON-ответа

JSON — это стандартный "язык" обмена данными между сервером и клиентом. Даже если вы не любите JSON, JSON любит вас (и ваши данные).

Пример: Привет, JSON!


const http = require('http');

const server = http.createServer((req, res) => {
  // Данные, которые хотим отправить
  const user = {
    name: 'Алиса',
    age: 30,
    isAdmin: true
  };

  // Устанавливаем заголовок: это JSON
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
  res.statusCode = 200;

  // Отправляем строку JSON
  res.end(JSON.stringify(user));
});

server.listen(3000, () => {
  console.log('Сервер слушает http://localhost:3000');
});

Ключевой момент:
- ВСЕГДА сериализуйте объект через JSON.stringify().
- Если попытаться отправить объект напрямую (res.end(user)), Node.js обидится и скажет, что не может отправить объект.

Проверим в браузере или через curl

  • Откройте http://localhost:3000 — увидите {"name":"Алиса","age":30,"isAdmin":true}
  • Или в терминале:
    curl http://localhost:3000

4. Установка других заголовков

Иногда нужно отправить дополнительные заголовки. Например, чтобы указать клиенту, что страница не должна кэшироваться, или чтобы разрешить кросс-доменные запросы (CORS).

Пример: Несколько заголовков


res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.setHeader('Cache-Control', 'no-store');
res.setHeader('X-Powered-By', 'Node.js');

Можно также использовать res.writeHead() — этот метод сразу устанавливает статус и все заголовки:


res.writeHead(200, {
  'Content-Type': 'text/html; charset=utf-8',
  'X-Custom-Header': 'МойКастом'
});

Внимание:
Если вы вызвали res.writeHead(), не используйте после этого res.setHeader() — заголовки уже отправлены.

5. Практический пример: HTML или JSON в зависимости от запроса

Давайте сделаем сервер, который отдаёт HTML при запросе /, а JSON — при запросе /api/user.


const http = require('http');

const server = http.createServer((req, res) => {
  if (req.url === '/') {
    // Главная страница — HTML
    res.writeHead(200, {
      'Content-Type': 'text/html; charset=utf-8'
    });
    res.end(`
      <h1>Главная страница</h1>
      <p>Перейдите на <a href="/api/user">/api/user</a> чтобы получить JSON.</p>
    `);
  } else if (req.url === '/api/user') {
    // API — JSON
    const user = { name: 'Боб', age: 25 };
    res.writeHead(200, {
      'Content-Type': 'application/json; charset=utf-8'
    });
    res.end(JSON.stringify(user));
  } else {
    // 404 Not Found
    res.writeHead(404, {
      'Content-Type': 'text/plain; charset=utf-8'
    });
    res.end('Страница не найдена');
  }
});

server.listen(3000, () => {
  console.log('Сервер запущен на http://localhost:3000');
});

Что здесь происходит:

  • Для разных URL — разные Content-Type и разные данные.
  • Если страница не найдена — отдаём 404 и простой текст.

6. Как правильно отправлять статус-коды

По умолчанию статус ответа — 200 (OK), но иногда нужно явно указать другой код:

  • 200 — всё хорошо
  • 201 — создано (например, при успешном POST-запросе)
  • 404 — не найдено
  • 500 — серверная ошибка

Пример:


res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end('Ошибка: страница не найдена');

Или через writeHead:


res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ result: 'Создано!' }));

7. Типичные ошибки при отправке HTML и JSON-ответов

Ошибка №1: Не установлен Content-Type
Если не указать заголовок Content-Type, браузер (или другой клиент) может неправильно интерпретировать ответ. Например, JSON отобразится как текст, а HTML — как странный набор символов.

Ошибка №2: Попытка отправить объект напрямую
Вызов res.end(user) — приведёт к ошибке. Нужно всегда сериализовать объект: res.end(JSON.stringify(user)).

Ошибка №3: Множественная отправка ответа
Если случайно вызвать res.end() несколько раз, Node.js выбросит ошибку: "Cannot set headers after they are sent to the client". Ответ можно отправить только один раз!

Ошибка №4: Использование res.setHeader() после res.writeHead() или res.end()
Заголовки должны быть установлены до отправки тела ответа. После вызова res.writeHead() или res.end() заголовки уже отправлены, и изменить их нельзя.

Ошибка №5: Отсутствие кодировки (charset)
Если не указать charset=utf-8, русские буквы могут отображаться "кракозябрами". Всегда добавляйте кодировку: text/html; charset=utf-8.

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