QA Interview Hub · База знань · Тести
API
Заголовки, кеш і CORS
Ключові заголовки
Заголовки — це метадані запиту й відповіді, і в них живе багато багів, які не видно в тілі.
| Заголовок | Де | Для чого |
|---|
Content-Type | Запит і відповідь | Формат тіла, наприклад application/json |
Accept | Запит | Який формат клієнт хоче отримати |
Authorization | Запит | Токен або облікові дані |
Location | Відповідь | URL створеного ресурсу або редіректу |
Cache-Control | Відповідь | Правила кешування |
ETag | Відповідь | Версія ресурсу для кешу й конкурентних змін |
Retry-After | Відповідь | Коли можна повторити запит після 429 чи 503 |
Set-Cookie | Відповідь | Встановити cookie з атрибутами безпеки |
Типові перевірки: Content-Type відповіді збігається з реальним вмістом; на Accept: application/xml, якщо API його не підтримує, сервер повертає 406, а не JSON мовчки; у Set-Cookie сесійної cookie є HttpOnly, Secure і SameSite; у відповіді немає заголовків, що розкривають версію сервера чи фреймворку.
На співбесіді: Я перевіряю не лише тіло, а й заголовки: Content-Type, Location після створення, правила кешу та атрибути безпеки cookie. Помилки в заголовках часто ламають клієнтів або створюють проблеми з безпекою.
ETag, 304 і Cache-Control
ETag — ідентифікатор версії ресурсу. Сервер віддає ETag: "v7". Наступного разу клієнт надсилає If-None-Match: "v7": якщо ресурс не змінився, сервер відповідає 304 Not Modified без тіла, і клієнт бере дані з кешу. Якщо змінився — 200 з новим тілом і новим ETag.
GET /accounts/42
If-None-Match: "v7"
HTTP/1.1 304 Not Modified
ETag: "v7"
ETag також захищає від втрачених оновлень: клієнт шле PUT з If-Match: "v7", і якщо хтось уже змінив ресурс, сервер повертає 412 Precondition Failed.
Cache-Control: no-cache vs no-store — класична пастка:
no-cache — зберігати можна, але перед використанням обов'язково перевірити актуальність на сервері (через ETag чи дату).no-store — не зберігати взагалі, ні в браузері, ні в проміжних кешах.max-age=60 — вважати відповідь свіжою 60 секунд; private — лише в браузері користувача, не в спільних кешах.
Для персональних і фінансових даних очікую no-store або щонайменше private, інакше баланс одного користувача може потрапити в CDN-кеш і віддатися іншому.
Тест-кейси: після зміни ресурсу ETag змінюється; старий ETag у If-None-Match дає 200, а не 304; відповіді з персональними даними не кешуються спільними кешами.
На співбесіді: ETag — версія ресурсу: з If-None-Match сервер повертає 304, якщо нічого не змінилося. no-cache означає «перевір перед використанням», а no-store — «не зберігай зовсім», і для фінансових даних я чекаю саме no-store.
CORS і preflight
CORS — механізм браузера, який дозволяє чи забороняє JavaScript на одному origin (схема + домен + порт) читати відповіді з іншого. Важливо: це обмеження саме браузера. Postman, curl і серверні клієнти CORS не застосовують, тому «в Postman працює, а в браузері ні» — типова ознака CORS-проблеми.
Для «непростих» запитів, наприклад з Content-Type: application/json, заголовком Authorization або методами PUT і DELETE, браузер спершу відправляє preflight — запит OPTIONS:
OPTIONS /api/transfers
Origin: https://app.bank.test
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization, content-type
Сервер має відповісти з Access-Control-Allow-Origin, Access-Control-Allow-Methods і Access-Control-Allow-Headers. Якщо чогось бракує, браузер не відправить основний запит, а в Console з'явиться CORS-помилка.
Що перевіряю:
- Дозволений origin фронтенду отримує правильні заголовки, а сторонній — ні.
- Немає
Access-Control-Allow-Origin: * разом з передачею cookie чи токенів — браузер таке й так заблокує, а відображення будь-якого Origin назад у відповіді — дірка в безпеці. - Preflight повертає 2xx і не вимагає авторизації.
На співбесіді: CORS — захист браузера, тому в Postman його не видно. Для непростих запитів браузер спочатку шле preflight OPTIONS, і я перевіряю, що сервер дозволяє лише довірені origin і правильні методи й заголовки.