Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «HTTP коди статусів». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**HTTP коди статусів** - це тризначні числа в кожній HTTP-відповіді, які повідомляють клієнту що сталося з його запитом. ```js res.status(200).json(user); // успіх res.status(404).send('Not found'); // ресурс не знайдено res.status(500).send('Error'); // сервер впав ``` **Головне правило:** перша цифра - категорія. 2xx = успіх, 4xx = помилка клієнта, 5xx = помилка сервера.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**HTTP коди статусів** - це тризначні числа, які сервер повертає в кожній HTTP-відповіді, щоб повідомити клієнту що сталося з його запитом. ## Теорія ### TL;DR - Уяви їх як повідомлення про доставку пошти: 200 = доставлено, 404 = адреса не існує, 500 = пошта сама зламала посилку - Перша цифра визначає категорію: 2xx успіх, 3xx перенаправлення, 4xx помилка клієнта, 5xx помилка сервера - `fetch()` встановлює `response.ok` в `true` тільки для 2xx - 401 = не автентифікований (потрібен вхід), 403 = автентифікований, але без дозволу - Правило: бачиш 4xx - виправляй запит, бачиш 5xx - чекай або пиши серверній команді ### Швидкий приклад ```javascript // 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 і вважає що все збережено. База даних відхиляє дані, нічого не зберігається, і ніхто не розуміє чому. ```javascript // Неправильно - обманюємо клієнта 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 для помилок сервера. ```javascript // Неправильно 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 і додавай затримку. ```javascript 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 із перевіркою підпису ```javascript // 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() з розрізненням типів помилок ```javascript 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 тригерить редирект, користувач бачить зрозумілу поведінку замість загального повідомлення про помилку.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.