HTTP коди статусів
HTTP коди статусів - це тризначні числа, які сервер повертає в кожній HTTP-відповіді, щоб повідомити клієнту що сталося з його запитом.
Теорія
TL;DR
- Уяви їх як повідомлення про доставку пошти: 200 = доставлено, 404 = адреса не існує, 500 = пошта сама зламала посилку
- Перша цифра визначає категорію: 2xx успіх, 3xx перенаправлення, 4xx помилка клієнта, 5xx помилка сервера
fetch()встановлюєresponse.okвtrueтільки для 2xx- 401 = не автентифікований (потрібен вхід), 403 = автентифікований, але без дозволу
- Правило: бачиш 4xx - виправляй запит, бачиш 5xx - чекай або пиши серверній команді
Швидкий приклад
// Express.js - запустити: npm init -y && npm i express && node server.js
const express = require('express');
const app = express();
app.get('/', (req, res) => res.status(200).send('Success')); // 200 OK
app.get('/missing', (req, res) => res.status(404).send('Not found')); // 404 Not Found
app.get('/error', (req, res) => { throw new Error(); }); // 500 Internal Server Error
app.listen(3000);
// curl localhost:3000/ → 200
// curl localhost:3000/missing → 404
// curl localhost:3000/error → 500Перший аргумент res.status() - це число, яке Express записує в статусний рядок відповіді перед відправкою заголовків.
П'ять категорій
Специфікація HTTP групує всі коди за першою цифрою:
- 1xx (Інформаційні) - сервер прийняв запит і ще обробляє. Рідко трапляються на практиці. Приклад: 100 Continue.
- 2xx (Успіх) - запит виконано. 200 для стандартного OK, 201 коли ресурс створено, 202 коли задача запущена але ще не завершена.
- 3xx (Перенаправлення) - ресурс переміщено. 301 постійне (оновлюй посилання), 302 тимчасове (перевіряй оригінальний URL).
- 4xx (Помилка клієнта) - щось у запиті неправильне. 400 невалідні дані, 401 не автентифікований, 403 автентифікований але без дозволу, 404 не знайдено, 429 забагато запитів.
- 5xx (Помилка сервера) - запит нормальний, але сервер впав. 500 загальна помилка, 503 тимчасово недоступний.
Коли який код використовувати
- Користувач надіслав валідні дані і ресурс створено →
201 Created - Запитуваний ресурс не існує →
404 Not Found - Запит без валідного токена →
401 Unauthorized - Токен валідний, але роль не має доступу →
403 Forbidden - База даних впала →
500 Internal Server Error - Технічне обслуговування →
503 Service Unavailable - Асинхронна задача поставлена в чергу →
202 Accepted
Типові помилки
Повертати 200 при помилках валідації. Це найпоширеніша помилка в джуніорських API. Клієнт отримує 200 і вважає що все збережено. База даних відхиляє дані, нічого не зберігається, і ніхто не розуміє чому.
// Неправильно - обманюємо клієнта
app.post('/users', (req, res) => {
if (!req.body.email) res.status(200).send('OK');
});
// Правильно
app.post('/users', (req, res) => {
if (!req.body.email) return res.status(400).send('Email required');
});Відправляти 500 на будь-яку помилку. Якщо користувач надіслав невалідний токен і ти повертаєш 500, логи заповнюються хибними тривогами, а фронтенд-команда не знає що проблема в токені. 4xx для помилок клієнта, 5xx для помилок сервера.
// Неправильно
app.use((err, req, res, next) => res.status(500).send('Error'));
// Правильно
app.use((err, req, res, next) => {
if (err.name === 'ValidationError') return res.status(400).send(err.message);
if (err.name === 'UnauthorizedError') return res.status(401).send('Invalid token');
res.status(500).send('Server error');
});Ігнорувати 429 у циклах запитів. Масові запити до API без перевірки на rate limit (обмеження частоти запитів) закінчуються блокуванням IP. Завжди перевіряй 429 і додавай затримку.
if (res.status === 429) {
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, retryCount)));
}Я бачив як продакшн-інтеграція впала через 1000 запитів до GitHub API в циклі без жодної затримки. IP заблокували за 30 секунд.
Де зустрічаються
- Express.js -
res.status(201).json(user)після POST /users - React Query -
if (!res.ok) throw new Error(res.status)всерединіqueryFn - Next.js API routes -
res.status(401).json({ error: 'Unauthorized' })в middleware - Stripe - 200 при успішному платежі, 402 Payment Required при нестачі коштів
- GitHub API - 404 для неіснуючого репозиторію, 422 при невалідному PR merge
Питання на співбесіді
Q: Яка різниця між 401 і 403?
A: 401 означає що запит не має валідних облікових даних - запропонуй користувачу увійти. 403 означає що дані валідні, але користувач не має дозволу на цей конкретний ресурс.
Q: Коли повертати 202 замість 200?
A: 202 Accepted використовують коли задача поставлена в чергу, але ще не виконана: наприклад, запуск генерації звіту або відправка email у фоні. Клієнт розуміє що треба почекати або перевірити статус пізніше.
Q: Яка різниця між 301 і 308?
A: Обидва постійні перенаправлення. Але 301 дозволяє браузеру змінити POST на GET при перенаправленні, а 308 зберігає оригінальний метод і тіло запиту. 308 безпечніший коли POST-дані мають пройти через redirect.
Q: API gateway повертає клієнтам 502. Що перевіряєш першим?
A: 502 Bad Gateway означає що проксі отримав невалідну відповідь від upstream-сервісу. Перевір чи запущений upstream, подивись його логи, перевір налаштування таймаутів і додай circuit breaker щоб один сервіс не валив весь ланцюжок.
Приклади
Валідація webhook із перевіркою підпису
// POST /webhook - перевіряємо підпис перед обробкою платіжної події
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, process.env.ENDPOINT_SECRET);
res.status(200).json({ received: true }); // 200: подія оброблена успішно
} catch (err) {
res.status(400).send(`Signature check failed: ${err.message}`); // 400: невалідні дані від клієнта
}
});Валідний webhook повертає 200. Невалідний підпис повертає 400, а не 500 - бо проблема в даних клієнта, а не в збої сервера.
Обробка кодів у fetch() з розрізненням типів помилок
async function loadUser(id) {
const res = await fetch(`/api/users/${id}`);
if (res.status === 404) return null; // відсутній користувач - нормальний стан
if (res.status === 401) {
window.location.href = '/login'; // перенаправляємо на сторінку входу
return;
}
if (!res.ok) throw new Error(`Error: ${res.status}`); // 500 та невідомі коди
return res.json();
}Коли 404 обробляється як нормальний стан, а 401 тригерить редирект, користувач бачить зрозумілу поведінку замість загального повідомлення про помилку.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.