Пошук уроків, статей та іншого контенту
Розберемо структуру HTTP-запиту й відповіді: стартовий рядок, заголовки та тіло повідомлення.
HTTP — це протокол обміну повідомленнями між клієнтом і сервером.
Під час одного обміну:
клієнт надсилає HTTP-запит;
сервер обробляє запит;
сервер надсилає HTTP-відповідь.
І запит, і відповідь мають подібну структуру:
стартовий рядок;
заголовки;
порожній рядок;
тіло повідомлення, якщо воно потрібне.
Схематично повідомлення виглядає так:
Стартовий рядок
Заголовок: значення
Інший-заголовок: значення
Тіло повідомленняПорожній рядок між заголовками й тілом є обов’язковим роздільником.
HTTP-запит надсилає клієнт: браузер, мобільний застосунок, інша програма або команда curl.
Приклад запиту:
POST /users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 38
{"name":"Anna","email":"anna@example.com"}Перший рядок складається з трьох частин:
POST /users HTTP/1.1POST — HTTP-метод;
/users — шлях до ресурсу;
HTTP/1.1 — версія протоколу.
Найпоширеніші методи:
GET — отримати дані;
POST — створити ресурс або передати дані;
PUT — повністю оновити ресурс;
PATCH — частково оновити ресурс;
DELETE — видалити ресурс.
У Node.js ці значення доступні через властивості об’єкта запиту:
request.method;
request.url;Наприклад:
request.method === "POST";
request.url === "/users";Заголовки містять додаткову інформацію про запит:
Host: example.com
Content-Type: application/json
Content-Length: 38
Authorization: Bearer tokenЗаголовки записують у форматі:
Назва: значенняУ Node.js заголовки доступні через request.headers:
console.log(request.headers);Назви заголовків у Node.js зазвичай представлені в нижньому регістрі:
request.headers["content-type"];
request.headers["user-agent"];Важливі заголовки:
Host — ім’я сервера;
Content-Type — формат тіла запиту;
Content-Length — розмір тіла в байтах;
Authorization — дані для автентифікації;
User-Agent — інформація про клієнта.
Тіло містить дані, які клієнт передає серверу. Наприклад, JSON:
{
"name": "Anna",
"email": "anna@example.com"
}Тіло найчастіше використовують із методами POST, PUT і PATCH. У запитах GET тіло зазвичай не використовують.
У Node.js тіло запиту надходить частинами. Тому його потрібно зібрати з подій data, а після завершення обробити в події end.
HTTP-відповідь надсилає сервер клієнту.
Приклад відповіді:
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 40
{"id":1,"name":"Anna","email":"anna@example.com"}Перший рядок відповіді називають статусним рядком:
HTTP/1.1 201 CreatedВін складається з:
версії HTTP;
коду статусу;
текстового пояснення статусу.
У Node.js сервер зазвичай формує цей рядок на основі властивостей:
response.statusCode = 201;
response.statusMessage = "Created";Найпоширеніші коди статусу:
200 OK — запит успішно оброблено;
201 Created — ресурс створено;
204 No Content — успіх без тіла відповіді;
400 Bad Request — некоректний запит;
401 Unauthorized — потрібна автентифікація;
403 Forbidden — доступ заборонено;
404 Not Found — ресурс не знайдено;
500 Internal Server Error — помилка на сервері.
Коди поділяють на групи:
1xx — інформаційні;
2xx — успішні;
3xx — перенаправлення;
4xx — помилка клієнта;
5xx — помилка сервера.
Сервер додає заголовки, які описують відповідь:
Content-Type: application/json
Content-Length: 40
Cache-Control: no-cacheУ Node.js заголовки відповіді можна встановити методом setHeader:
response.setHeader("Content-Type", "application/json");Тіло відповіді містить дані для клієнта. Наприклад:
{
"message": "Користувача створено"
}У Node.js тіло можна надіслати методом response.end:
response.end(JSON.stringify({ message: "Користувача створено" }));Після виклику response.end() відповідь завершується. Після цього не можна додавати до неї заголовки або ще раз надсилати тіло.
Модуль node:http надає серверу два основні об’єкти:
request — вхідний запит;
response — вихідна відповідь.
Приклад простого сервера:
const http = require("node:http");
const server = http.createServer((request, response) => {
let body = "";
// Збираємо частини тіла запиту
request.on("data", (chunk) => {
body += chunk;
});
// Після отримання всього запиту формуємо відповідь
request.on("end", () => {
console.log("Метод:", request.method);
console.log("URL:", request.url);
console.log("Заголовки:", request.headers);
console.log("Тіло:", body);
const responseBody = JSON.stringify({
method: request.method,
url: request.url,
receivedBody: body || null,
});
response.statusCode = 200;
response.setHeader("Content-Type", "application/json; charset=utf-8");
response.setHeader("Content-Length", Buffer.byteLength(responseBody));
response.end(responseBody);
});
});
server.listen(3000, () => {
console.log("Сервер запущено на http://localhost:3000");
});Збережіть код у файлі server.js і запустіть:
node server.jsТепер можна надіслати запит в іншому терміналі:
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name":"Anna","email":"anna@example.com"}'Сервер отримає:
метод POST;
URL /users;
заголовок content-type;
JSON у тілі запиту.
У відповідь він поверне JSON із даними отриманого запиту.
Статус і заголовки потрібно встановити до надсилання тіла:
response.statusCode = 201;
response.setHeader("Content-Type", "application/json");
response.end(JSON.stringify({ id: 1 }));Також статус і заголовки можна передати одним об’єктом:
response.writeHead(201, {
"Content-Type": "application/json",
});
response.end(JSON.stringify({ id: 1 }));Після першого виклику response.write() або response.end() HTTP-заголовки вважаються надісланими.
Заголовки й тіло виконують різні функції.
Заголовки описують повідомлення:
Content-Type: application/json
Authorization: Bearer tokenВони повідомляють:
який формат має тіло;
який клієнт надіслав запит;
який розмір має повідомлення;
чи потрібна автентифікація.
Тіло містить основні дані:
{
"name": "Anna"
}Наприклад, Content-Type: application/json повідомляє, що тіло потрібно трактувати як JSON. Сам заголовок не містить даних користувача — вони знаходяться в тілі.
Розглянемо послідовність для створення користувача.
Запит клієнта:
POST /users HTTP/1.1
Content-Type: application/json
{"name":"Anna"}Сервер:
читає метод POST;
визначає шлях /users;
перевіряє заголовок Content-Type;
читає тіло запиту;
створює користувача;
формує відповідь.
Відповідь сервера:
HTTP/1.1 201 Created
Content-Type: application/json
{"id":1,"name":"Anna"}Клієнт аналізує код 201, заголовки та тіло відповіді.
Між заголовками й тілом має бути порожній рядок. Він відділяє метадані від даних.
Content-TypeЯкщо тіло містить JSON, бажано вказати:
Content-Type: application/jsonБез цього клієнт або сервер може неправильно інтерпретувати дані.
Тіло запиту може надходити кількома частинами. Не слід очікувати, що всі дані будуть доступні одразу після створення сервера.
Потрібно дочекатися події end:
let body = "";
request.on("data", (chunk) => {
body += chunk;
});
request.on("end", () => {
console.log(body);
});Після response.end() відповідь завершена:
response.end("Готово");Повторний виклик response.end() або спроба змінити заголовки після цього призведе до помилки.
Код 404 не є текстом помилки в тілі. Це окрема частина статусного рядка:
response.statusCode = 404;
response.end("Сторінку не знайдено");Тут:
404 — код статусу;
"Сторінку не знайдено" — тіло відповіді.
HTTP-запит надсилає клієнт, а HTTP-відповідь — сервер.
Повідомлення складається зі стартового рядка, заголовків і тіла.
У запиті стартовий рядок містить метод, URL і версію HTTP.
У відповіді стартовий рядок містить версію HTTP, код статусу й текст статусу.
Заголовки описують запит або відповідь.
Тіло містить дані повідомлення.
У Node.js дані запиту доступні через request.method, request.url і request.headers.
Тіло запиту потрібно зібрати до події end.
Статус і заголовки відповіді потрібно встановити до виклику response.end().