HTTP статус-коди
Зміст
(status code) — тризначне число в стартовому рядку відповіді, яким сервер описує долю запиту: чи його опрацьовано і що вкладено у відповідь. Усі валідні коди лежать у діапазоні 100–599. Це найкоротше повідомлення в протоколі: одним числом сервер каже, на чиєму боці проблема і що робити далі.
Для QA це базовий інструмент діагностики. Червоний тест, (flakiness) у , «нічого не працює на стейджі» — усе це починається з питання «а який код повернув сервер?». Ця глава — канон теми на сайті, інші глави посилаються сюди. Перевірка кодів усередині API-тестів — схеми, тіла помилок, контракт — лишається в розділі про API-тестування.
Де живе код і що каже перша цифра
Ось сирий (raw) обмін даними:
GET /api/users/42 HTTP/1.1
Host: example.com
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 53
{"id": 42, "name": "Ada", "email": "ada@example.com"}
Перший рядок відповіді — стартовий рядок статусу: версія протоколу, число і коротка (reason phrase, тут OK). Фраза необовʼязкова: RFC 9110 називає її optional, а RFC 9112 велить клієнту її ігнорувати як ненадійний канал. HTTP/3 узагалі не визначає способу переносити версію чи reason phrase зі статус-рядка HTTP/1.1, а в HTTP/2 статус несе єдиний псевдозаголовок :status. Висновок для тесту: число, а не рядок.
Перша цифра задає клас відповіді, а клас — стратегію реакції.
| Клас | Значення | Що це означає для клієнта |
|---|---|---|
| 1xx | інформаційні (informational) | проміжна відповідь, а не остаточна — фінальний код прийде слідом |
| 2xx | успіх (success) | запит опрацьовано — читай тіло й заголовки |
| 3xx | перенаправлення (redirection) | сам запит нормальний, але потрібна ще одна дія |
| 4xx | помилка клієнта (client error) | запит містить помилку або не може бути виконаний |
| 5xx | помилка сервера (server error) | сервер не впорався з очевидно валідним запитом |
Головна лінія розлому — між 4xx і 5xx, і проходить вона там, де ти шукаєш винного: «із запитом щось не так» проти «сервер не впорався».
2xx: успіх теж буває різним
200 OK — загальний успіх, але конкретний його зміст залежить від методу. 201 Created каже більше: запит виконано і як результат створено новий ресурс; це типова відповідь на POST і частину PUT, за домовленістю з заголовком Location на адресу нового ресурсу. 204 No Content — успіх без тіла, але зі значущими заголовками: спроба розпарсити з 204 JSON впаде, і тест покаже помилку парсингу там, де все спрацювало.
Асерт на статус перевіряє контракт, а не «щось повернулося». 200 замість 201 на створення — легітимна претензія до API. Але й твій expect(200) зламається, щойно почне чесно віддавати 201.
Метод — друга вісь, з якою код читають у парі
Метод каже, що клієнт хоче зробити з ресурсом; код каже, чим це скінчилося. Нарізно вони втрачають половину змісту.
POST просить цільовий ресурс обробити передане подання — тому 201 на ньому природний. PUT створює або повністю замінює стан ресурсу. DELETE просить розірвати звʼязок ресурсу з його функціональністю — це не гарантія фізичного видалення даних. 405 означає, що метод серверу відомий, але цільовий ресурс його не підтримує: адреса правильна, дієслово — ні. А 415 Unsupported Media Type — через формат вмісту (Content-Type чи Content-Encoding), і саме він, а не 400, канонічний на непідтримуваний чи помилковий Content-Type.
Ще одне, що видно лише в парі: HTTP описує наміри, а не гарантує поведінку реалізації. GET, який мутує стан, технічно можливий — і саме тому це баг контракту. І навпаки: «зайвий» OPTIONS перед POST у панелі Network — це CORS preflight, а не баг. Детальніше — у главі HTTP: методи, структура, заголовки.
Тіло відповіді: коли воно є, а коли його немає
Запит і відповідь мають однакову будову: стартовий рядок, необовʼязкові заголовки, порожній рядок як межа метаданих і необовʼязкове тіло (body). Що в тілі й скільки його — кажуть Content-Type і Content-Length.
У запиті тіло зазвичай несуть POST, PUT і PATCH. Тіло в GET синтаксис не забороняє, але воно не має загальновизначеного значення й не може змінити зміст чи ціль запиту — тому складні структури «для читання» передають через POST.
У відповіді тіла немає у трьох упізнаваних випадках: HEAD (тут це пряма заборона — сервер не має права надсилати вміст), 204 No Content і 304 Not Modified. Жоден із трьох не є помилкою чи «порожньою відповіддю»: заголовки в них значущі, а тіла там і не мало бути.
4xx: сервер зрозумів і відмовив
400 Bad Request — сервер не може або не буде обробляти запит через помилку клієнта, зокрема зламаний синтаксис. 422 Unprocessable Content — запит сформований коректно, але не може бути виконаний через семантичні помилки. Простими словами: 400 — «я не зрозумів, що ти написав», 422 — «я зрозумів, але так не можна».
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Grace", "email": "grace@example.com", "age": -5}
HTTP/1.1 422 Unprocessable Content
409 Conflict — запит конфліктує з поточним станом ресурсу: зайнятий email, дублікат, конкурентне редагування. 429 Too Many Requests — перевищено звернень; відповідь може містити Retry-After (невідʼємне число секунд або HTTP-дату).
І про межу з 5xx: на відверто кривий ввід добре спроєктований сервер має відповісти 400 чи 422, а не впасти з 500. Тому 500 на невалідному вводі — знахідка сама собою, навіть коли ввід справді кривий.
Наша практика (не канон). У пайплайні 429 — одне з найпідступніших джерел : паралельні гатять в один ендпоінт, спрацьовує ліміт, частина тестів червоніє «випадково». Симптом упізнаваний: локально зелено, у CI плаває. Стандарту під це немає; у командах, з якими ми працювали, лікується поважанням Retry-After у , зниженням паралелізму на «гарячих» ендпоінтах і моканням мережі, коли сам ліміт не є метою тесту.
401 проти 403: хто ти й що тобі можна
| 401 Unauthorized | 403 Forbidden | |
|---|---|---|
| Питання | «Хто ти?» | «Тобі можна?» |
| Зміст за каноном | бракує валідних облікових даних | сервер зрозумів запит і відмовляється виконати |
| Обовʼязковий заголовок | WWW-Authenticate | — |
| Чи допоможе логін | так, це стадія автентифікації | ні, повторний вхід нічого не змінить |
Назви обох кодів читаються не так, як звучать, тому канон розводить їх за змістом: 401 — про брак валідних даних для входу, і відповідь мусить нести WWW-Authenticate (на практиці вимогу часто порушують); 403 — про відмову виконати зрозумілий запит. розводить і самі поняття: автентифікація — процедура встановлення особи, авторизація — наданий дозвіл.
Два застереження, які RFC робить прямо. Перше: запит може бути заборонений із причин, не повʼязаних з обліковими даними, — тож «прийшов 403, отже роль не та» це гіпотеза, а не висновок. Друге: сервер, який хоче приховати саме існування забороненого ресурсу, може віддати 404 замість 403.
Поруч живе третій код, який плутають із 401: 407 Proxy Authentication Required — той самий сценарій від , з парою Proxy-Authenticate і Proxy-Authorization. І окрема поведінка: на валідні, але недостатні облікові дані сервер має відповісти 403 — і, на відміну від 401 і 407, браузер нової спроби не запропонує. Канон теми — Автентифікація та авторизація.
Наша практика (не канон). Оскільки сервер має право приховати ресурс під 404, у негативному сценарії з правами очікувати варто або 403, або 404. Специфікація описує право сервера, а не тестову практику, тож жорсткий асерт рівно на 403 робить тест крихким — звіряйся з контрактом конкретного API.
OAuth 2.0: звідки в потоці беруться свої коди
Сам механізм розібрано в главі Автентифікація та авторизація — тут лише коди, які цей потік додає. OAuth 2.0 — фреймворк делегованого доступу: він дає сторонньому застосунку обмежений доступ до сервісу від імені власника ресурсу. Ролей чотири: власник ресурсу, клієнт, сервер авторизації, сервер ресурсів. У потоці з кодом авторизації браузер спершу йде на ендпоінт авторизації (authorization endpoint), і лише потім клієнт міняє код на токен — уже сервер-до-сервера; саме тому пароль користувача до клієнта не потрапляє. Токен предʼявляють заголовком Authorization зі схемою Bearer: це Bearer-токен, який працює в кожного, хто ним володіє, тож TLS обовʼязковий.
Що з цього дає коди, яких у звичайному CRUD не буває:
401тут не завжди про «протух логін»: це штатний сигнал оновити access-токен через refresh і повторити запит.- Заголовок
Authorizationзнімається на редиректі — звідси «раптовий401» у флоу, де клієнт токен точно слав. - Код авторизації одноразовий і короткоживучий: повторний обмін того самого коду має провалитися. Готовий негативний тест.
- При невідповідному
redirect_uriсервер має повідомити власника ресурсу і не редиректити на невалідну адресу — тобто очікувати тут3xxнеправильно. Звірка адреси робиться точним рядковим збігом; єдиний виняток — номер порту вlocalhost-адресах нативних застосунків.
Термінологічна межа, яку варто тримати чітко: OAuth 2.0 — про авторизацію, а — надбудова над ним для автентифікації; «вхід через Google» технічно спирається саме на неї.
Редиректи: 301, 302, 307, 308
Редирект (redirect) — відповідь із кодом 3xx і заголовком Location, у якому вказано адресу, куди клієнту треба піти далі.
Усередині класу дві незалежні осі: постійність і збереження методу з тілом.
| Код | Назва | Постійність | Метод і тіло |
|---|---|---|---|
| 301 | Moved Permanently | постійно | незмінні лише для GET; інший метод може стати GET |
| 302 | Found | тимчасово | те саме: не-GET може стати GET, тіло втрачається |
| 307 | Temporary Redirect | тимчасово | метод і тіло не змінюються |
| 308 | Permanent Redirect | постійно | метод і тіло не змінюються |
Постійні редиректи означають, що стару адресу більше не слід використовувати; MDN додає, що й RSS-читалки оновлюють у себе адресу. Але RFC це саме пропонує, а не гарантує, і сам каже, що пропозицію зазвичай ігнорують. Тобто «після 301 усі оновлять посилання» — очікування, а не норма протоколу.
Специфікація не передбачала зміни методу, але реальні клієнти її роблять — саме тому додали 307 і 308. Тонкість, яку варто тримати точно: нормативну заборону змінювати метод RFC 9110 прописує лише для 307, а про тіло не говорить у жодному з цих місць — його збереження документує MDN. Сам 308 молодший (червень 2014), і RFC застерігає, що розпізнають його не всюди; поширене «308 живе окремим документом» описує стан до 2022 року — RFC 9110 обсолетнув RFC 7538 і визначає цей код сам.
Ще три члени родини. 303 See Other навпаки — навмисно змінює метод на GET (тіло втрачається); типово після обробки форми. 300 Multiple Choices — ручний вибір із переліку варіантів. А 304 Not Modified формально теж 3xx, але «перенаправляє» на локальну копію — про нього нижче.
Петля редиректів — коли перенаправлення зациклюються і сторінка ніколи не завантажується; зазвичай це проблема конфігурації сервера, і якщо сервер її помічає, то віддає 500. Поруч тиха ціна: кожен редирект коштує зайвого запиту, тож внутрішні правильніше прибирати, виправивши посилання.
І чому редиректу часто «не видно»: браузери й більшість HTTP-клієнтів ідуть за ним автоматично, помітний виняток — curl без прапорця -L. Перенаправити можна ще двома способами поза HTTP: <meta>-refresh у HTML і зміна адреси через DOM — обидва статус-коду не мають узагалі.
Наша практика (не канон). Автопрямування зручне й небезпечне водночас: у коді ти бачиш фінальний 200, навіть якщо між ним був 301, — і мовчки пропускаєш зламану ланку ланцюга. Канонічного припису під тестову техніку немає; ми вимикаємо автопрямування й асертимо проміжний код разом із Location.
// Playwright APIRequestContext: не йти за редиректом, перевірити його явно
const res = await request.get('/old-path', { maxRedirects: 0 });
expect(res.status()).toBe(301);
expect(res.headers()['location']).toBe('/new-path');
У UI-тестах ланцюг редиректів (на сторінку логіну й назад) — часте джерело флаку: очікування ловить URL, який існує лише мить. Надійніше чекати на фінальний стан сторінки.
304 і умовні запити
Коли збережена відповідь більше не придатна до віддачі напряму, кеш надсилає умовний запит (conditional request) із валідатором: ETag перетворюється на If-None-Match, Last-Modified — на If-Modified-Since.
GET /api/config HTTP/1.1
If-None-Match: "a1b2c3"
HTTP/1.1 304 Not Modified
ETag: "a1b2c3"
304 означає: збережену відповідь можна оновити метаданими й перевикористати, тіло повторно не передається. Тонкість, за яку чіпляються: копія при 304 валідна, а не застаріла — RFC каже, що клієнт уже має валідне подання, і сервер лише спрямовує його скористатися збереженою копією так, ніби це тіло 200. MDN тут суперечить сам собі на одній сторінці: у прозі копія «була застарілою», у таблиці — «ще свіжа». Канон тут RFC. Механіка кешу — у главі Кешування.
Ресурс і ендпоінт: чому 404 неоднозначний
Ресурс (resource) — концептуальне відображення на набір сутностей, а не сама сутність у конкретний момент часу; ендпоінт (endpoint) — конкретна адреса, за якою до нього звертаються. Саме звідси росте неоднозначність 404: в API цей код покриває щонайменше три різні ситуації.
- Невідомий шлях — такого маршруту немає взагалі (одрук у слагу, не та версія API).
- Відсутній обʼєкт за валідним ендпоінтом — маршрут є, запису немає: видалено, не створено , не те середовище.
- Прихована заборона — ресурс існує, але сервер віддає
404замість403, щоб не розкрити факт його існування.
Є й четверте, суто технічне джерело «404 на рівному місці»: схема й хост нечутливі до регістру, а шлях і рядок запиту — чутливі.
Тому корисний рефлекс при 404 — не «баг», а три питання: чи існує маршрут, чи існує обʼєкт у цьому середовищі і чи не ховає сервер відмову. Ресурси й адреси розібрані в главах REST API та формати даних і URL і кодування.
Посередники: 502 і 504 — і чому 503 не з їхньої родини
Між браузером і застосунком майже завжди стоїть ще хтось. (intermediary) має три форми: проксі (proxy) — вузол, якого обирає клієнт; (gateway, він же reverse proxy) — вузол, що назовні поводиться як origin-сервер, а всередину транслює запити іншим серверам; (tunnel) — сліпий ретранслятор, який повідомлень не змінює.
502 Bad Gateway за означенням віддає сервер, який діє як шлюз або проксі й отримав невалідну відповідь від внутрішнього сервера. 504 Gateway Timeout — той самий сервер у тій самій ролі, коли не дочекався відповіді вчасно. Обидва означають «зламалася ланка за посередником»: застосунок цих кодів міг не віддавати взагалі й навіть не знати про запит.
А 503 Service Unavailable до їхньої родини не належить, хоч його регулярно туди зараховують: він означає, що сам сервер тимчасово не здатен обробити запит через перевантаження чи планові роботи. Різниця не косметична: 502/504 відправляють шукати за шлюзом, 503 — до самого сервісу. 500 Internal Server Error лишається узагальненою помилкою: сервер не знає, як опрацювати ситуацію, і не має доречнішого коду 5xx.
І останнє: є посередники, які фільтрують чи перенаправляють трафік без відома відправника — на рівні протоколу вони не відрізняються від на шляху. Тому запит крізь корпоративний фаєрвол чи публічний Wi-Fi може повестися інакше без жодної зміни в застосунку.
Наша практика (не канон). Масові однотипні 502/503/504 одразу після релізу — частіше стан середовища, ніж баг продукту: у процесі, стенд «прогрівається», база під навантаженням. Статистики під це немає, тож правило в нас процедурне: спершу переконайся, що середовище піднялося, і лише потім заводь баг на продукт.
Типові помилки
- Виглядає як помилка парсингу, а насправді
204— тіла в цій відповіді й не мало бути. - Виглядає як зелений тест на створення, а насправді асерт прибитий до
200— зламається, щойно ендпоінт почне віддавати201. - Виглядає як «редиректу немає», а насправді клієнт пішов за ним сам і показав фінальний
200. - Виглядає як «
POSTперенаправився і зламався», а насправді це штатна поведінка301/302— метод підмінено наGET, тіло втрачено; зберігають їх307і308. - Виглядає як проблема прав, а насправді
401— користувач не автентифікований. Дзеркально:403повторним логіном не лікується. - Виглядає як «прав вистачає, бо
403не прийшов», а насправді сервер приховав ресурс під404. - Виглядає як
400на помилковомуContent-Type, а насправді канонічний код тут415. - Виглядає як баг застосунку, а насправді
502/504— зламана ланка за шлюзом, якої застосунок не віддавав. - Виглядає як застаріла копія при
304, а насправді копія валідна.
Підсумок
- Перша цифра — стратегія реакції:
4xxозначає «виправляй запит»,5xx— «сервер не впорався з валідним запитом». Фразу поруч із кодом не асертять: вона необовʼязкова. - Код читають у парі з методом і тілом:
201ізLocationна створення,204і304без тіла,405про метод,415про формат вмісту. - У родині
3xxпостійність і збереження методу — різні осі:307/308зберігають метод і тіло,301/302дозволяють підмінити метод наGETразом із втратою тіла. 401— «не впізнав»,403— «впізнав і відмовляю». Але403може бути не про права, а замість нього сервер має право віддати404.502і504віддає посередник,503— сам сервер. Застосунок цих кодів міг не бачити, тож шукати причину в його коді марно.
Можливі питання
- «Чим
401відрізняється від403?» Перевіряють, чи розводиш автентифікацію й авторизацію і чи знаєш проWWW-Authenticate. Сильна відповідь додає застереження:403не обовʼязково про ролі, а замість нього може прийти404. - «
301проти302— у чому різниця?» Дивляться на дві осі одразу: постійність і долю методу з тілом. Згадка307/308— сильний хід. - «Що станеться з
POST, якщо сервер відповість301?» Питання на розуміння: метод може статиGET, тіло — зникнути. - «Що означає
304і хто його ініціює?» Слухають, чи знаєш, що запит умовний і починається з клієнта з валідатором. - «Прийшов
502— де шукаєш причину?» Перевіряють, чи відрізняєш коди посередника від кодів застосунку. - «Чому
404не завжди означає “немає такого запису”?» Хочуть почути розрізнення ресурсу й ендпоінта плюс варіант із прихованою забороною. - «Коли сервер має віддати
422, а коли400?» Класика на межу «не зрозумів» / «зрозумів, але так не можна».
Джерела
Де живе код і що каже перша цифра
- RFC 9110 — HTTP Semantics — означення статус-коду, діапазон 100–599, класи відповідей і межа між
4xxі5xx. - MDN — HTTP response status codes — довідник класів і окремих кодів із типовими причинами появи.
- RFC 9112 — HTTP/1.1 (message syntax) — вимога до клієнта ігнорувати reason phrase як ненадійний канал.
- RFC 9114 — HTTP/3 — у HTTP/3 спосіб переносити версію й reason phrase не визначено.
- RFC 9113 — HTTP/2 — статус у HTTP/2 несе єдиний псевдозаголовок
:status.
- RFC 9110 — HTTP Semantics — семантика успішних відповідей і звʼязок коду з методом запиту.
- MDN — HTTP response status codes —
200,201ізLocation,204без тіла і наслідок для парсингу.
Метод — друга вісь, з якою код читають у парі
- RFC 9110 — HTTP Semantics — семантика
POST,PUT,DELETE, означення415і межа з400. - MDN — HTTP request methods — методи як «дієслова» запиту й наміри, які вони позначають.
- MDN — HTTP response status codes —
405: метод відомий серверу, але не підтримується цільовим ресурсом. - MDN — Cross-Origin Resource Sharing (CORS) — preflight-запит
OPTIONSперед основним запитом.
Тіло відповіді: коли воно є, а коли його немає
- MDN — HTTP messages — будова повідомлення й те, які методи мають тіло запиту.
- RFC 9110 — HTTP Semantics —
Content-TypeіContent-Length, заборона тіла у відповіді наHEAD, семантика тіла вGET. - MDN — HTTP response status codes —
204і304як відповіді без тіла зі значущими заголовками.
4xx: сервер зрозумів і відмовив
- MDN — HTTP response status codes —
400проти422,409як конфлікт зі станом ресурсу,429і заголовокRetry-After. - RFC 9110 — HTTP Semantics — клас
4xxяк помилка запиту й вимога відповідати4xx, а не падати з5xx. - RFC 6585 — Additional HTTP Status Codes — код
429як обмеження частоти запитів.
401 проти 403: хто ти й що тобі можна
- RFC 9110 — HTTP Semantics — означення
401і403, вимогаWWW-Authenticate, заборона з причин поза обліковими даними й право віддати404замість403. - MDN — HTTP authentication —
407із пароюProxy-Authenticate/Proxy-Authorizationі поведінка при валідних, але недостатніх даних. - MDN — HTTP response status codes —
401як «не автентифіковано»,403як відомий серверу клієнт без прав. - ISTQB Glossary — автентифікація як процедура встановлення особи, авторизація як наданий дозвіл.
OAuth 2.0: звідки в потоці беруться свої коди
- RFC 6749 — The OAuth 2.0 Authorization Framework — чотири ролі, потік із кодом авторизації, одноразовість коду й поведінка при невідповідному
redirect_uri. - RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage — схема
Bearer, Bearer-токен і обовʼязковий TLS. - RFC 9700 — Best Current Practice for OAuth 2.0 Security — вимога точного рядкового збігу
redirect_uri. - MDN — Authorization header — заголовок
Authorizationзнімається на крос-оріджин редиректі. - OpenID Connect Core 1.0 — шар ідентичності над OAuth 2.0.
- MDN — Redirections in HTTP —
Location, постійні й тимчасові редиректи, доля методу й тіла в301/302/303/307/308,300, петля редиректів, ціна зайвого запиту,meta-refresh і JS-редирект. - RFC 9110 — HTTP Semantics — заміна посилань як пропозиція, яку зазвичай ігнорують; нормативна заборона змінювати метод для
307; вік коду308. - curl — manual page — без прапорця
-Lклієнт за редиректом не йде.
- RFC 9111 — HTTP Caching — умовний запит із валідатором, пари
ETag/If-None-MatchіLast-Modified/If-Modified-Since, зміст304. - RFC 9110 — HTTP Semantics — при
304клієнт уже має валідне подання ресурсу. - MDN — Redirections in HTTP —
304усередині класу3xxяк перенаправлення на локальну копію. - MDN — HTTP caching — ревалідація збереженої відповіді та її результат.
Ресурс і ендпоінт: чому 404 неоднозначний
- Roy T. Fielding — Architectural Styles and the Design of Network-based Software Architectures, ch.5 (REST) — ресурс як концептуальне відображення, а не сутність у конкретний момент.
- MDN — HTTP response status codes —
404як невідомий шлях і як відсутній обʼєкт за валідним ендпоінтом. - RFC 9110 — HTTP Semantics — право сервера віддати
404замість403, щоб приховати існування ресурсу. - RFC 3986 — URI Generic Syntax — чутливість шляху й рядка запиту до регістру проти нечутливих схеми й хоста.
Посередники: 502 і 504 — і чому 503 не з їхньої родини
- RFC 9110 — HTTP Semantics — три форми посередника, означення
502і504через роль шлюзу,503як стан самого сервера, перехоплювальні вузли поза вибором клієнта. - MDN — HTTP response status codes —
500як узагальнена серверна помилка й типові причини502,503,504.
Що таке HTTP статус-код і що каже його перша цифра?
Це тризначне число на початку відповіді, яким сервер підсумовує долю запиту: опрацьовано чи ні і що покладено у відповідь. Валідні значення вкладаються в проміжок від 100 до 599, а перша цифра ділить їх на пʼять класів і задає клієнтові стратегію реакції. 1xx — відповідь проміжна, остаточна прийде слідом; 2xx — запит виконано, читай тіло й заголовки; 3xx — із запитом усе гаразд, але потрібен ще один крок; 4xx — проблема в самому запиті; 5xx — запит виглядав валідним, а спіткнувся сервер. Для тестувальника це найдешевша діагностика: число вже показує, на чиєму боці шукати винного, ще до логів і коду. Конкретний код (401 це чи 403, 502 чи 503) уточнює картину, але напрямок пошуку задає клас.
Чому в автотестах асертять число коду, а не текст поруч із ним?
Бо (reason phrase) — ненадійний канал. RFC 9110 вважає її необовʼязковою, RFC 9112 вимагає, щоб клієнт на неї не спирався, у HTTP/2 статус приїжджає єдиним псевдозаголовком :status, а HTTP/3 місця під таку фразу не має взагалі. Тобто сервер, чи зміна версії протоколу можуть переписати OK на будь-що, і жодна специфікація цього не порушить. «текст відповіді дорівнює Not Found» ламається на рівному місці, асерт на 404 — ні. Це той рідкісний випадок, коли правильна практика випливає прямо з букви специфікації, а не з досвіду.
Де проходить головна межа: 4xx проти 5xx?
Там, де змінюється адресат претензії. 4xx означає, що з запитом щось не так — синтаксис, дані, права, метод, формат; виправляти треба на боці клієнта. 5xx означає, що запит виглядав нормальним, а зламався сам сервер. Практичний наслідок для баг-репорта: 4xx веде до самого запиту — тесту, , контракту, — а 5xx до бекенду й інфраструктури. Є одне важливе перехрестя: на відверто кривий ввід сервер має відповісти кодом класу 4xx, і якщо він натомість падає з 500, це самостійна знахідка, навіть коли ввід справді сміттєвий. Тобто 500 на негативному тесті — не «очікувано, бо дані погані», а баг.
Чим 201 Created відрізняється від 200 OK і навіщо це знати тестувальнику?
200 — універсальний успіх, зміст якого залежить від методу; 201 повідомляє більше: у результаті запиту зʼявився новий ресурс. Типове місце — POST і частина PUT, а адресу новоствореного ресурсу за домовленістю кладуть у заголовок Location. Для QA тут дві сторони однієї монети. З одного боку, 200 на створення — легітимна претензія до API: код недоговорює, клієнту нема звідки взяти адресу створеного обʼєкта. З іншого — жорсткий expect(200) у твоєму тесті зламається того дня, коли бекенд почне чесно віддавати 201, і це буде падіння тесту, а не продукту. Тому асерт на статус варто читати як перевірку контракту, а не як «щось повернулося».
Тест успішно виконав запит, але падає на розборі JSON. Що могло статися?
Найпоширеніший сценарій — 204 No Content: запит опрацьовано, але тіла у відповіді немає й не мало бути. Парсер отримує порожній рядок, кидає помилку, і в звіті це виглядає як зламаний , хоча насправді все відпрацювало штатно. Значуща інформація в такій відповіді лежить у заголовках, і саме їх треба перевіряти. Той самий симптом дає 304 Not Modified і будь-яка відповідь на HEAD. Правильна реакція — не «сервер повернув порожнечу», а перевірка коду перед парсингом: спершу статус, потім тіло, і лише якщо воно за контрактом має бути.
У яких випадках тіла у відповіді немає за правилами, а не через баг?
Таких упізнаваних випадків три: відповідь на HEAD, 204 No Content і 304 Not Modified. Для HEAD це навіть не домовленість, а заборона: надсилати вміст серверу не дозволено, бо метод існує заради самих метаданих. 204 каже «успіх, показувати нема чого», 304 — «бери свою збережену копію». Порожнеча тут не збій: усе потрібне лежить у заголовках, і саме їх треба читати замість тіла. У запитах картина дзеркальна: тіло зазвичай везуть POST, PUT і PATCH, тоді як тіло в GET синтаксис пропускає, але загальновизначеного змісту воно не має і ціль запиту не змінює — тому громіздкі критерії пошуку відправляють окремим POST, а не пхають у GET.
Коли сервер має відповісти 405, а коли 415?
Ці коди відповідають на різні питання, хоч обидва звучать як «мені це не підходить». 405 Method Not Allowed — про дієслово: серверу метод знайомий, просто конкретний ресурс із ним не працює. Класична ситуація — DELETE на колекцію, яка вміє тільки GET і POST: адреса правильна, дія — ні. 415 Unsupported Media Type — про формат вмісту, тобто про Content-Type чи Content-Encoding: сервер відмовляється розбирати те, що ти прислав. Це важлива деталь для негативних тестів: канонічна відповідь на кривий або непідтримуваний Content-Type — саме 415, а не загальний 400.
Де межа між 400 і 422?
400 Bad Request виставляють, коли сервер відмовляється братися за запит через помилку на боці клієнта — типово через побитий синтаксис. 422 Unprocessable Content означає, що запит зібраний коректно, але виконати його не вийде через семантику. Найкоротша формула, яка добре заходить на співбесіді: 400 — «я не розібрав, що ти написав», 422 — «я все розібрав, але так не буває». Приклад різниці: обірваний JSON — це 400, а синтаксично бездоганний JSON з віком -5 або датою виїзду раніше за дату заїзду — це 422. Обидва коди сидять у класі 4xx, тобто в обох випадках правити треба запит; різниця в тому, що саме правити — форму чи зміст.
Що означає 409 Conflict і чим він відрізняється від 400 та 422?
409 — це конфлікт запиту з поточним станом ресурсу: email уже зайнятий, запис із таким ключем існує, документ хтось редагує паралельно. У продуктовому сенсі це нормальна ділова відповідь, а не поломка: запит і зібраний коректно, і зрозумілий, просто виконати його заважає те, що вже лежить на сервері. Звідси й межа із сусідами по класу: 400 і 422 кажуть правити сам запит — форму або зміст, — а 409 каже, що із запитом усе гаразд і справа в тому, що вже лежить на сервері. Для тесту з цього випливає конкретна річ: сценарій створення з фіксованою поштою на другому прогоні законно отримає 409, бо ця пошта вже зайнята першим, — і правити тут треба , а не продукт.
Що таке 429 і чому він робить пайплайн нестабільним?
429 Too Many Requests означає, що клієнт перевищив дозволену частоту звернень; відповідь може нести заголовок Retry-After, у якому вказано, скільки чекати, — невідʼємне число секунд або HTTP-дата. Симптом у CI дуже впізнаваний: локально все зелене, а в тести плавають без жодної логіки. Причина зазвичай механічна — паралельні одночасно гатять в той самий ендпоінт, ліміт спрацьовує, і частина запитів отримує замість даних. Лікується це не збільшенням , а трьома речами: мають читати Retry-After, паралелізм на найгарячіших ендпоінтах варто зрізати, а мережу — замокати там, де сам ліміт перевіряти не треба. Окремо варто памʼятати: якщо ти тестуєш саме rate limiting, 429 — очікуваний результат, і глушити його не можна.
Чим 401 відрізняється від 403?
401 Unauthorized відповідає на питання «хто ти?», 403 Forbidden — на питання «тобі можна?». За каноном 401 означає брак валідних облікових даних, і така відповідь мусить нести заголовок WWW-Authenticate — на практиці цю вимогу порушують регулярно. 403 означає, що сервер запит зрозумів і виконувати його відмовляється; повторний вхід тут нічого не змінить, бо стадія автентифікації вже пройдена. Плутанину підживлюють самі назви: 401 називається «Unauthorized», хоча йдеться про автентифікацію. Розвести поняття допомагає : автентифікація — це процедура встановлення особи, авторизація — наданий дозвіл. І окремий нюанс, за який дають бали: якщо облікові дані валідні, але їх повноважень бракує, коректна відповідь — 403, і браузер, на відміну від 401, нової спроби входу вже не запропонує.
Прийшов 403. Чи можна з цього зробити висновок, що бракує ролі?
Ні, це гіпотеза, а не висновок, і RFC говорить про це прямо: відмовити можуть із причин, які взагалі не стосуються облікових даних, — стан обʼєкта, налаштування середовища, правило на посереднику. Друге застереження ще важливіше для тестів: сервер, який не хоче розкривати сам факт існування ресурсу, має право віддати 404 замість 403. Практичний наслідок для негативного сценарію про права — обидва результати, звіряючись із контрактом конкретного API; асерт, прибитий рівно до 403, легко зробить тест ламким. Дзеркальна пастка теж поширена: «403 не прийшов, значить прав вистачає» — хибний висновок, бо відмову могли сховати під 404.
Що таке 407 і чим він відрізняється від 401?
407 Proxy Authentication Required — це той самий сюжет про «назвися», але вимагає автентифікації не цільовий сервер, а між тобою і ним. Пара заголовків тут своя: Proxy-Authenticate у відповіді й Proxy-Authorization у наступному запиті. Для QA це насамперед підказка при дебагу корпоративного оточення: якщо запити зі стенда всередині мережі отримують 407, справа не в застосунку і не в токені користувача, а в тому, що трафік іде крізь проксі, який хоче свої облікові дані. Плутати 407 з 401 — типова помилка: перший заводить у дебрі коду автентифікації застосунку, хоча правильне місце пошуку — мережева конфігурація.
У чому різниця між 301, 302, 307 і 308?
Усередині класу 3xx працюють дві незалежні осі, і плутають їх саме тому, що намагаються запамʼятати чотири коди списком. Перша вісь — постійність: 301 і 308 кажуть, що адреса змінилася назавжди і стару використовувати більше не варто, 302 і 307 — що переїзд тимчасовий. Друга вісь — доля методу й тіла: 307 і 308 переносять їх у наступний запит без змін, а 301 і 302 дозволяють клієнту підмінити метод на GET, і тіло при цьому губиться. Історія тут така: специфікація зміни методу не передбачала, але реальні клієнти її робили — тож 307 і 308 додали, щоб зафіксувати сувору поведінку явно. Дві деталі для сильної відповіді: нормативно RFC 9110 забороняє підміняти метод тільки в описі 307, а незмінність тіла документує MDN; і хоча 308 колись жив окремим документом, з 2022 року його визначає той самий RFC 9110.
Сервер відповів 301 на POST. Що станеться з методом і тілом?
Метод може перетворитися на GET, а тіло — просто зникнути, і формально це не баг клієнта: коди 301 і 302 таку підміну допускають. Виглядає це в тестах дуже неприємно: запит нібито пройшов, фінальна відповідь 200, але дані на сервер не доїхали, бо друга частина ланцюга була вже іншим запитом без тіла. Якщо потрібно, щоб POST лишився POST, правильні коди — 307 (тимчасово) і 308 (постійно). Додаткова складність у тому, що браузери й більшість HTTP-клієнтів ідуть за редиректом (redirect) автоматично, тож у коді видно лише фінальний результат; помітний виняток — curl, який без прапорця -L за редиректом не піде. Саме тому редирект варто перевіряти явно: вимкнути автопрямування, заасертити проміжний код і заодно заголовок Location.
Навіщо існує 303 See Other, якщо є 302?
303 — єдиний із родини, який змінює метод на GET навмисно, а не «дозволяє клієнту». Класичне застосування — після обробки форми: сервер приймає POST, виконує дію і відправляє браузер забрати результат окремим GET. Тіло вихідного запиту при цьому не переноситься, і це закладена поведінка, а не втрата. Різниця з 302 тонка, але саме її люблять питати: 302 описує тимчасовий переїзд і мовчазно допускає підміну методу, а 303 цю підміну робить частиною свого змісту. Поруч у класі живуть ще два коди, які не є редиректом у звичному сенсі: 300 Multiple Choices пропонує вибрати варіант вручну, а 304 Not Modified відправляє клієнта до його ж локальної копії.
Що означає 304, хто його ініціює і чи застаріла копія в кеші?
Ініціює його клієнт: коли віддати збережену відповідь напряму вже не можна, кеш іде на сервер із умовним запитом (conditional request) і додає валідатор — збережений ETag їде в заголовку If-None-Match, а дата з Last-Modified — в If-Modified-Since. Сервер порівнює валідатор і, якщо ресурс не змінився, відповідає 304 без тіла: збережену копію можна оновити метаданими й використати повторно, трафік на тіло не витрачається. Тепер тонкість, на якій ловлять: копія в цей момент не застаріла, а валідна — RFC виходить із того, що клієнт уже має придатне подання ресурсу, і сервер лише каже скористатися ним так, ніби це тіло відповіді 200. Формулювання «сервер підтвердив, що стара копія ще годиться» — побутове й нешкідливе, а от «копія була протухла» суперечить специфікації. Для тестів 304 у мережевій панелі — ознака робочої ревалідації, а не помилки.
Чому 404 в API — неоднозначний код?
Тому що під ним ховаються щонайменше три різні історії. Перша — маршруту не існує взагалі: друкарська помилка у слазі, звернення до старої версії API, не той префікс. Друга — маршрут є, а обʼєкта немає: запис видалили, фікстура не створилася, тест дивиться не в те середовище. Третя — заборона, яку сервер навмисно замаскував, щоб не розкривати існування ресурсу. Корінь неоднозначності термінологічний: ресурс — поняття концептуальне, це відображення на певний набір сутностей, а не сама сутність, зафіксована в моменті, тоді як ендпоінт — просто адреса, за якою до нього стукають. Є й четверте, суто технічне джерело: регістр байдужий схемі й хосту, але не шляху й рядку запиту, тож /api/Users/42 і /api/users/42 це різні адреси. Тому рефлекс при 404 — не заводити баг, а поставити три питання: чи взагалі є такий маршрут, чи лежить потрібний запис саме в цьому середовищі і чи не маскує код відмову.
Прийшов 502. Де шукати причину і чим від нього відрізняється 503?
502 Bad Gateway за означенням віддає не застосунок, а вузол, що працює як (gateway) чи проксі й отримав від внутрішнього сервера відповідь, яку не зміг визнати валідною; 504 Gateway Timeout — той самий вузол у тій самій ролі, тільки відповіді він не дочекався. Обидва означають «зламалася ланка за посередником», і застосунок про такий запит міг узагалі не дізнатися — тому шукати причину в його коді марно, дивитися треба на балансувальник, шлюз і те, що за ними. 503 Service Unavailable до цієї родини не належить, хоч його туди регулярно записують: він каже, що сам сервіс тимчасово не здатен обробити запит — перевантаження або планові роботи. 500 Internal Server Error лишається загальною відмовкою: сервер не знає, що робити, і доречнішого коду в класі 5xx не має. Практичне продовження відповіді: масові однотипні 502 чи 504 одразу після релізу частіше означають, що середовище ще не піднялося, ніж що в продукті зʼявився баг, — спершу перевіряють стенд, і лише потім заводять тікет.
Чому в OAuth-флоу 401 не завжди означає «протухла сесія»?
Бо в делегованому доступі 401 — це штатний сигнал у нормальному житті токена: access-токен короткоживучий, і відповідь 401 каже клієнту оновити його через refresh і повторити запит. Тобто одиничний 401 у логах такого флоу — не інцидент, а частина протоколу. Друга типова причина «раптового 401» ще підступніша: заголовок Authorization знімається на редиректі, тож клієнт токен слав, а до цільового сервера він не доїхав. Поруч живуть ще два готові негативні тести з тієї ж області: код авторизації одноразовий і короткоживучий, тож повторний обмін того самого коду має провалитися; а при невідповідному redirect_uri сервер має сказати про це власникові ресурсу й нікого на непідтверджену адресу не відправляти — тому очікувати там 3xx неправильно. І термінологічна межа, яку люблять питати поруч: OAuth 2.0 — про авторизацію, а автентифікацію дає надбудова над ним, , на яку технічно спирається звичний «вхід через Google».
Три кейси, у яких вирішує, куди піде наступна година: триаж червоної за кодами замість читання логів наосліп, контракту створення й редиректу в Playwright і негативний тест прав, який не ламається від того, що сервер приховав ресурс. Скрізь — що дивитися і чому саме так.
Кейс 1. Ранкова сюїта червона: триаж за кодом
Класична картина понеділка: 40 упалих тестів, у кожному «request failed». Перш ніж відкривати логи застосунку, варто витягнути зі звіту самі коди — вони вже сортують проблему за адресатом. Перша цифра каже, на чиєму боці шукати, конкретний код підказує перше місце.
| Код у звіті | Перша гіпотеза | Куди дивитися |
|---|---|---|
401 | тест не автентифікувався: токен не отриманий, протух або не доїхав | сетап авторизації, час життя токена, чи є WWW-Authenticate у відповіді |
403 або 404 на захищеному ресурсі | ролі не ті — або сервер приховав ресурс | контракт API: що саме він обіцяє віддавати на відмову |
404 на всій сюїті | не той базовий URL чи версія API | конфіг середовища, префікс маршруту, регістр у шляху |
409 | запис із такими значеннями вже існує: конфлікт із поточним станом ресурсу | унікальність тестових значень, стан даних у середовищі |
415 | тест шле не той Content-Type | заголовки клієнта, серіалізація тіла |
422 | дані валідні синтаксично, але не за змістом | генератор тестових даних, граничні значення |
429 | рейт-ліміт від паралельних воркерів | кількість воркерів, Retry-After, чи потрібен тут реальний бекенд |
500 | баг сервера на валідному вводі | логи застосунку — це знахідка, навіть якщо ввід кривий |
502 або 504 | зламана ланка за шлюзом | балансувальник, стан деплою, доступність внутрішніх сервісів |
503 | сам сервіс не приймає навантаження | стенд ще піднімається або йдуть планові роботи |
Далі — два вузли, у яких найчастіше плутають адресата.
- Однотипні
502/503/504на всій сюїті одразу після релізу — спершу стан середовища, а не баг продукту. Застосунок цих кодів міг не віддавати взагалі:502і504приходять від , який не дочекався або не зрозумів внутрішній сервер. Заводити тікет на продукт, поки стенд не піднявся, — гарантований спосіб витратити день на чужу проблему. 500не «пробачають» через поганий ввід. Якщо негативний тест шле сміття і отримує500, це окрема знахідка: коректною відповіддю тут був би400чи422. Тест при цьому може бути формально зеленим, якщо в асерті стоїть «код не з класу2xx» — і саме так реальні дефекти проїжджають повз.429виглядає як , але має адресу. Симптом дуже характерний: на локальній машині все стабільно, а в тести плавають. Перед тим як накидати , варто подивитися, скільки одночасно б'ють в один і чи є в відповідіRetry-After— його значення і є правильною паузою.
Кейс 2. Playwright: асерт контракту, а не «щось повернулося»
Створення ресурсу і редирект — два місця, де слабкий асерт роками виглядає зеленим і нічого не перевіряє. Почнемо зі створення: контракт тут не лише про код, а й про адресу нового обʼєкта.
import { test, expect } from '@playwright/test';
test('POST /api/users віддає 201 і адресу створеного ресурсу', async ({ request }) => {
const res = await request.post('/api/users', {
// унікальна пошта: фіксоване значення дасть 409 на другому прогоні
data: { name: 'Ada', email: `ada+${Date.now()}@example.com` },
});
expect(res.status()).toBe(201);
const location = res.headers()['location'];
expect(location, 'без Location клієнту нема звідки взяти адресу створеного обʼєкта').toBeTruthy();
// адреса з Location має вести на реально створений ресурс
const created = await request.get(location);
expect(created.status()).toBe(200);
});
Редирект перевіряють так само явно — інакше клієнт піде за ним сам і покаже фінальний 200, приховавши всю ланку.
test('стара адреса звіту постійно переїхала на нову', async ({ request }) => {
// нуль редиректів: клієнт зупиняється й віддає нам саму проміжну відповідь
const res = await request.get('/legacy/report', { maxRedirects: 0 });
expect(res.status(), 'переїзд постійний, отже 301, а не 302').toBe(301);
expect(res.headers()['location']).toBe('/reports/summary');
});
Що дивитися і чому:
expect(200)на створення — крихкий асерт. Він упаде того дня, коли бекенд почне чесно віддавати201, і це буде падіння тесту, а не продукту. Дзеркально: якщо API віддає200там, де створює ресурс, це претензія до контракту, і її варто озвучити, а не підлаштувати тест.204не парсять. Якщо ендпоінт за контрактом віддає успіх без тіла, спроба розібрати JSON зробить із зеленого сценарію фальшиве падіння. Спершу статус, потім тіло — і лише якщо воно взагалі передбачене.- Фінальний
200нічого не каже про ланцюг. Автопрямування зручне саме тим, чим і небезпечне: зламана проміжна ланка залишається невидимою. Вимкнене автопрямування плюс асерт наLocationперетворює редирект на перевірюваний контракт. POSTчерез301втрачає тіло. Якщо в ланцюзі є редирект, а метод має лишитися незмінним, у контракті мають стояти307або308. Побачили301наPOST— це не «дивна поведінка клієнта», а закладена специфікацією можливість підмінити метод наGET.- У UI-тестах ланцюг редиректів ловити не варто взагалі. Проміжний URL (сторінка логіну й назад) існує мить, і очікування на нього — готовий . Чекати треба на фінальний стан сторінки, а самі коди перевіряти на рівні API.
Кейс 3. Негативний тест прав: 401, 403 і чесний 404
Найпоширеніша помилка в тестах доступу — прибити асерт рівно до 403. Специфікація дозволяє серверу приховати існування ресурсу під 404, тож такий тест червоніє від зміни політики приватності, а не від дефекту.
import { test, expect } from '@playwright/test';
// сервер має право не розкривати існування чужого ресурсу
const DENIED = [403, 404];
const readerToken = process.env.READER_TOKEN as string;
test('читач не дістає чужий рахунок', async ({ request }) => {
const res = await request.get('/api/accounts/999', {
headers: { Authorization: `Bearer ${readerToken}` },
});
expect(DENIED).toContain(res.status());
});
test('без облікових даних приходить 401, а не 403', async ({ request }) => {
const res = await request.get('/api/accounts/999');
expect(res.status()).toBe(401);
// за каноном 401 мусить нести цей заголовок; на практиці вимогу часто порушують
expect(res.headers()['www-authenticate']).toBeTruthy();
});
Коли 404 прилетів там, де його не чекали, помилка — одразу заводити баг. Спершу три питання, і кожне має дешеву перевірку.
| Питання | Як перевірити | Що означає «так» |
|---|---|---|
| Чи існує маршрут? | той самий шлях з іншим методом: 405 замість 404 доводить, що адреса жива | проблема не в маршруті, а в обʼєкті |
| Чи існує обʼєкт саме тут? | пошук запису прямо в цьому середовищі, не в тому, де його створювали | фікстура не доїхала або тест дивиться не туди |
| Чи не схована за кодом відмова? | той самий запит під адміністративним токеном | ресурс є, і 404 тут — маскування 403 |
Що дивитися і чому:
401і403не взаємозамінні в асерті. Перший означає «не впізнав» і лікується логіном, другий — «впізнав і відмовляю», і повторний вхід нічого не змінить. Тест, який приймає обидва коди «про всяк випадок», перестає ловити регресію автентифікації.403не доводить, що справа в ролі. Заборона могла прийти з причин, ніяк не повʼязаних з обліковими даними, — стан обʼєкта чи правило на . Формулювання дефекту «користувачу не вистачає прав» тут треба спершу підтвердити, а не припустити.405— безкоштовний детектор живого маршруту. Він приходить, коли адреса правильна, а метод ресурс не підтримує; отже сама адреса існує. Це найшвидший спосіб відсікти першу з трьох гіпотез про404.- Регістр у шляху має значення. Схема й хост до нього нечутливі, а шлях і рядок запиту — чутливі, тож
/api/Users/42цілком законно віддасть404там, де/api/users/42працює.
Клас коду і контракт
- Можу назвати всі пʼять класів і сказати, якої дії кожен вимагає від клієнта, не заглядаючи в довідник.
- Знаю різницю
4xxvs5xxяк межу відповідальності: «правити запит» проти «зламався сервер». - Розумію, чому треба число, а не поруч: вона необовʼязкова, клієнт не має на неї спиратися, а в HTTP/2 статус несе
:status. - Можу пояснити, чому
500на завідомо кривому вводі — самостійна знахідка, а не очікуваний результат негативного тесту.
Успіх, тіло відповіді й метод
- Знаю різницю
200vs201і те, що адресу створеного ресурсу за домовленістю кладуть уLocation. - Розумію, чому прибитий
expect(200)на створення — крихкий асерт, а не строгіша перевірка. - Можу назвати три випадки, коли тіла у відповіді немає штатно:
HEAD(тут це заборона),204,304. - Знаю різницю
405vs415: перший про метод, якого ресурс не підтримує, другий про формат вмісту — і що на кривийContent-Typeканонічний саме415.
Помилки клієнта: 400, 422, 409, 429
- Можу розвести
400vs422: зламаний синтаксис проти коректно зібраного, але семантично неможливого запиту. - Знаю, що
409— конфлікт із поточним станом ресурсу (зайнятий email, дублікат, конкурентне редагування), а не проблема форми чи змісту самого запиту. - Можу пояснити, як
429перетворює паралельний на і чому лікують йогоRetry-Afterта паралелізмом, а не .
Доступ: 401, 403, 407 і OAuth
- Знаю різницю
401vs403(«хто ти» проти «тобі можна»), памʼятаю про обовʼязковийWWW-Authenticateі тримаю в голові межу ISTQB: автентифікація — процедура, авторизація — наданий дозвіл. - Розумію, чому
403не доводить брак ролі, чому сервер має право віддати замість нього404і чому негативний тест прав має обидва коди. - Не плутаю
407із401: перший приходить від з пароюProxy-AuthenticateтаProxy-Authorization, тобто веде в мережеву конфігурацію, а не в код застосунку. - Знаю дві особливості кодів у делегованому доступі:
401буває штатним сигналом оновити токен через refresh, а заголовокAuthorizationзнімається на редиректі.
Редиректи 3xx і 304
- Знаю дві осі всередині
3xx: постійність (301/308проти302/307) і збереження методу з тілом (307/308проти301/302). - Можу відповісти, що станеться з
POSTпри301, і памʼятаю, що клієнти йдуть за редиректом самі (помітний виняток —curlбез-L), тож у тесті видно лише фінальний200. - Можу пояснити, що
304ініціює клієнт умовним запитом із валідатором і що копія в цей момент валідна, а не застаріла.
404 і серверні коди
- Можу розвести ресурс і , знаю три ситуації під одним
404(немає маршруту, немає обʼєкта, схована заборона) і памʼятаю, що регістр байдужий схемі й хосту, але не шляху. - Можу пояснити, чому
502і504віддає , а503— сам сервіс, і чому масові5xxвідразу за релізом спершу перевіряють як стан середовища.
Квіз
Перед стартом
- Питань: 17
- Поріг «зараховано»: ≥70% правильних відповідей.
- Результат впливає на прогрес; завалені питання підуть у чергу повторення.
- Квіз впливає на компліт теми: тема стає «пройдено», лише коли прочитано теорію І квіз складено на ≥70%.
Питання
Що таке HTTP статус-код?

