vyvchy
    Теми розділу

    03 · Веб і мережі для AQA

    HTTP: методи, структура, заголовки

    Зміст

    Кожен клік урешті стає HTTP-повідомленням. Логін, збереження форми, підвантаження списку — це все запити, і саме тут видно те, чого не видно в інтерфейсі: чи фронтенд шле той метод, чи дані поїхали в адресі замість тіла, чи токен узагалі доїхав. Тест, що логіниться без UI, , яка готує стан одним запитом, баг-репорт із доказом замість «у мене не працює» — усе це починається з уміння прочитати повідомлення по кістках.

    Ця глава — повний виклад теми на сайті, інші глави посилаються сюди по структуру повідомлення й семантику методів. Мета одна: дивлячись на запит, за пів хвилини сказати, що в ньому не так.

    Одна структура на запит і на відповідь

    HTTP-повідомлення (message) — це спосіб обміну даними між клієнтом і сервером; типів рівно два: запит (request), яким клієнт ініціює дію, і відповідь (response), якою сервер відповідає. Будова в них однакова: стартовий рядок (start-line), необовʼязковий набір заголовків (headers), порожній рядок і необовʼязкове тіло (body). Стартовий рядок разом із заголовками називають «головою» (head) повідомлення, усе після — тілом.

    Порожній рядок — не косметика, а частина синтаксису: саме він каже парсеру, що метадані скінчилися й далі йдуть дані.

    POST /api/login HTTP/1.1
    Host: app.example.com
    Content-Type: application/json
    Accept: application/json
    Content-Length: 46
    
    {"email":"qa@example.com","password":"secret"}
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    Content-Length: 52
    
    {"token":"eyJhbGciOiJIUzI1NiJ9...","expiresIn":3600}

    Стартовий рядок запиту зветься request-line і має три частини: метод, ціль запиту (request target — зазвичай шлях із рядком запиту) і версію протоколу. Стартовий рядок відповіді — це status-line, і в ньому теж три частини: версія, і (reason phrase). Фраза суто інформативна — вона допомагає людині, а не машині, і RFC 9112 рекомендує клієнту її ігнорувати (SHOULD) як ненадійний канал. Практичний наслідок: у тесті число, а не рядок.

    Заголовки — це поля, що передаються перед вмістом. У HTTP/1.x кожен заголовок — нечутлива до регістру назва, двокрапка й значення, усе в одному рядку (Content-Type і content-type — те саме); чутливість самого значення залежить від конкретного заголовка.

    Відповідь

    HTTP/1.1 200 OK
    версія + код + фраза

    Content-Type, Content-Length
    заголовки

    порожній рядок

    тіло: дані або пояснення

    Запит

    POST /api/login HTTP/1.1
    метод + ціль + версія

    Host, Content-Type, Accept
    заголовки

    порожній рядок

    тіло: дані на сервер

    Відповідь

    HTTP/1.1 200 OK
    версія + код + фраза

    Content-Type, Content-Length
    заголовки

    порожній рядок

    тіло: дані або пояснення

    Запит

    POST /api/login HTTP/1.1
    метод + ціль + версія

    Host, Content-Type, Accept
    заголовки

    порожній рядок

    тіло: дані на сервер

    Метод: намір, а не гарантія

    Метод (HTTP method) — перший елемент стартового рядка запиту; він каже, що клієнт хоче зробити з ресурсом за вказаною адресою. Методи ще звуть «дієсловами» (verbs). Крім власної семантики кожен метод описують трьома наскрізними властивостями: безпечність, і кешованість.

    (safe method) — той, чия визначена семантика фактично «лише читання»: клієнт не просить і не очікує зміни стану ресурсу на сервері. Безпечні — GET, HEAD, OPTIONS і TRACE. Це точніше за звичне «без побічних ефектів», і різниця змістова: специфікація прямо дозволяє реалізації мати побічні ефекти під безпечним методом (її власний приклад — запис у лог доступу), важливо лише те, що клієнт цієї поведінки не замовляв і не відповідає за неї. Мету поділу джерело називає теж прямо: щоб (spiders) і працювали без страху щось зламати.

    Звідси головне для тестування: HTTP описує наміри, а не гарантує поведінку реалізації. Ніщо не заважає зробити GET /users/42/delete, який видаляє користувача, — і саме тому це баг контракту, а не особливість. Краулер або префетч браузера «клікне» таке посилання без жодного наміру шкодити, тож заводьте баг, а не адаптуйте тест.

    МетодЩо робитьБезпечнийІдемпотентнийКешований
    GETотримати подання ресурсутактактак
    HEADте саме без тіла у відповідітактактак
    OPTIONSдізнатися доступні опціїтактакні
    TRACEвіддзеркалити повідомленнятактакні
    PUTстворити або замінити цілкомнітакні
    DELETEрозірвати звʼязок із ресурсомнітакні
    POSTнадіслати на обробкунініумовно
    PATCHзмінити частковонініумовно
    CONNECTслужбовийнініні

    Кешовані за замовчуванням лише GET і HEAD; POST і PATCH — умовно, коли відповідь явно містить дані про свіжість і відповідний Content-Location. Самі правила свіжості й кеш-заголовки розбирає глава «Кешування».

    Розбір методів

    GET запитує передачу поточного подання цільового ресурсу — це основний механізм отримання даних. Тіла він нести не повинен: синтаксис його не забороняє, але семантично воно не має загальновизначеного значення й не може змінити зміст чи ціль запиту, тож клієнту рекомендовано його не генерувати. Поведінка серверів і при цьому непередбачувана, тому складну структуру для «читання» передають через POST.

    POST просить цільовий ресурс обробити передане подання за власною семантикою ресурсу — саме тому він ані безпечний, ані ідемпотентний: що станеться від повтору, протокол не знає.

    PUT створює або повністю замінює стан ресурсу переданим поданням; після успішного PUT наступний GET має повернути еквівалентне подання. PATCH застосовує часткові зміни — різниця в тому, чим є тіло: у PUT це змінена версія ресурсу, у PATCH — набір інструкцій, як його змінити.

    PUT /api/users/42 HTTP/1.1
    Content-Type: application/json
    
    {"name":"Ivan","email":"ivan@example.com","role":"admin"}
    PATCH /api/users/42 HTTP/1.1
    Content-Type: application/json
    
    {"role":"admin"}

    У PUT ви зобовʼязані передати цілісне подання — інакше ризикуєте затерти те, чого не передали. Формат тіла PATCH одним стандартом не задано: є application/json-patch+json (RFC 6902) і application/merge-patch+json (RFC 7396), але багато API приймають власний частковий JSON, тож дивіться контракт, а не припускайте.

    DELETE просить сервер розірвати звʼязок між цільовим ресурсом і його поточною функціональністю. Це не гарантія фізичного видалення даних — рядок у базі цілком може лишитися з прапорцем.

    HEAD ідентичний GET, але надсилати тіло сервер не має права: тут MUST NOT. Заголовки він SHOULD віддати ті самі, що й для GET, — проте MAY пропустити поля, значення яких визначається лише під час генерації вмісту, і прикладом джерело називає рівно Content-Length. Тому HEAD — дешева перевірка існування ресурсу для , але асерт «файл важить рівно 1 МБ» на ньому потенційно : заголовка може просто не бути, і це право сервера, а не баг.

    OPTIONS запитує доступні опції взаємодії з ресурсом без виконання дії над ним. У браузері це насамперед CORS preflight: специфікація зобовʼязує браузер «промацати» непростий запит, спитавши в сервера підтримувані методи саме через OPTIONS. Звідси «зайвий» OPTIONS перед POST чи PATCH у мережевій панелі — це preflight, а не баг; механіку дозволів розбирає глава «CORS і політика одного походження». Друга тонкість: відповідь OPTIONS — вхідна точка, а не вердикт, бо реальний перелік перевіряють, надсилаючи запити різними методами.

    Службові. TRACE задуманий для тестування й відлагодження: він наказує серверу віддзеркалити отримане повідомлення клієнту — і попри позірну нешкідливість у певних сценаріях ним крадуть облікові дані. CONNECT не є ані безпечним, ані ідемпотентним, ані кешованим. Увімкнений службовий метод у проді — тема конфігураційних дір із розділу про безпеку, не протокольна.

    Ідемпотентність: про стан сервера, а не про відповідь

    Ідемпотентність (idempotency) — властивість, за якої кілька однакових запитів дають на сервері той самий очікуваний ефект, що й один такий запит. Інакше кажучи: стан сервера після одного виклику й після N однакових викликів поспіль однаковий.

    Ось тонкість, на якій плутаються найчастіше: ідемпотентність стосується стану сервера, а не тіла відповіді — коди й заголовки повторних викликів можуть відрізнятися.

    Ідемпотентні: GET, HEAD, OPTIONS, TRACE, PUT, DELETE. Неідемпотентних три, а не два, як зазвичай кажуть: POST, PATCH і CONNECT — останній випадає з переліків лише тому, що в прикладному тестуванні не трапляється.

    • PUT ідемпотентний, бо замінює ресурс цілком: той самий PUT /users/42 десять разів залишає ресурс у тому самому стані, що й після першого.
    • DELETE ідемпотентний попри різні коди: перший виклик поверне 200/204, другий — 404, але стан сервера незмінний — ресурсу немає й немає.
    • POST неідемпотентний: два однакові POST /orders створять два замовлення. Звідси дублі від подвійного кліку по кнопці оплати без захисту.
    • PATCH неідемпотентний за специфікацією — RFC 5789 каже це прямо. Патч «додай +1 до лічильника» щоразу дає новий результат; конкретний запит можна сформувати ідемпотентним, але від методу цього ніхто не вимагає.
    СерверТестСерверТестзамовлення 42 немаєзамовлення 42 немає — стан той самийDELETE /orders/42204 No ContentDELETE /orders/42 (повтор)404 Not FoundСерверТестСерверТестзамовлення 42 немаєзамовлення 42 немає — стан той самийDELETE /orders/42204 No ContentDELETE /orders/42 (повтор)404 Not Found

    Усі безпечні методи ідемпотентні, але не навпаки: PUT і DELETE ідемпотентні й при цьому змінюють стан. Ідемпотентність і кешованість — теж різні осі: PUT і DELETE ідемпотентні, але не кешовані.

    Практична цінність пряма. Ідемпотентні запити можна безпечно повторювати після чи мережевого збою, а POST — ні: якщо тест на мережі, знання методу відповідає на головне питання, чи безпечний тут . І асерт на повторний DELETE має враховувати семантику: 404 на другий виклик — очікувана поведінка, а не порушення ідемпотентності. Повторний PUT/DELETE як сценарій тестування API і Idempotency-Key — тема розділу «API-тестування».

    Наша практика (не канон). Далі — те, як поводяться клієнти, з якими ми працювали; окремої норми під це немає. HTTP-бібліотеки часто вмикають автоматичний ретрай саме для GET, PUT і DELETE й не вмикають для POST — тож перевіряйте налаштування клієнта, перш ніж списувати дублі на застосунок.

    Заголовки: метадані повідомлення

    Заголовки — це метадані повідомлення: поля після стартового рядка й перед тілом, що уточнюють його семантику. Вони описують відправника, формат вмісту, автентифікацію, правила кешу.

    Content-Type описує медіа-тип (media type, MIME type) тіла, яке передається зараз: application/json, application/x-www-form-urlencoded, multipart/form-data, text/html; charset=utf-8. Заголовок двосторонній — у запиті описує тіло клієнта, у відповіді тіло сервера. Помилковий Content-Type — класична причина , і нормативний код тут 415, а не 400: сервер відмовляється обслуговувати запит, бо вміст у форматі, який метод на цьому ресурсі не підтримує. Сервер, що віддає на це 400, від специфікації відступає, і в баг-репорті це варто називати.

    Content-Length вказує розмір тіла в байтах — щоб знав, скільки читати.

    Accept — навпаки, побажання клієнта: у якому форматі він хоче відповідь. Механізм зветься узгодженням вмісту (content negotiation), а ваги q нормовані в діапазон від 0 до 1; за відсутності q перевага дорівнює 1. Край діапазону варто знати точно: q=0 — це не «найменш бажаний», а «неприйнятно», тобто пряма відмова від формату (найменш бажаний із прийнятних — 0.001). Там же обмеження запису: більше трьох цифр після коми відправник генерувати не має права.

    Content-TypeAccept
    Що описуєщо є в тілі заразщо клієнт хоче отримати
    Напрямокопис наявного тілапобажання щодо майбутньої відповіді
    Де єу запиті й у відповідіпереважно в запиті
    Мнемоніка«ось що я вклав у конверт»«ось у якому форматі хочу відповідь»

    У межах одного запиту вони спокійно відрізняються: клієнт шле форму (Content-Type: application/x-www-form-urlencoded), а відповідь хоче в JSON (Accept: application/json). Кеш-заголовки живуть у главі «Кешування», Set-Cookie — у главі «Кукі, сесії та сховище браузера».

    Заголовки, якими тест керує запитом

    Authorization несе облікові дані. Схема Bearer несе Bearer-токен (часто JWT), і специфікація задає форму дослівно: слово Bearer, пробіл, токен. Схема Basic — це base64("логін:пароль"), причому роздільником вважається перша двокрапка, тож двокрапка в логіні робить пару невалідною. тут кодування, а не шифрування: сама специфікація каже, що схема не вважається безпечною без зовнішнього захищеного каналу на кшталт TLS, бо логін і пароль ідуть мережею відкритим текстом (модальність — SHOULD NOT, не заборона). Чому саме TLS це лікує — глава «HTTPS, TLS і безпека».

    Якщо сервер вимагає автентифікації, він відповідає 401 разом із WWW-Authenticate, який підказує схему. Проксі робить те саме іншою парою — 407 і Proxy-Authenticate; плутати їх не можна. Будову JWT усередині Bearer розбирає глава «Автентифікація та авторизація».

    User-Agent ідентифікує клієнтське ПЗ, і сервери іноді змінюють поведінку залежно від нього — мобільна версія проти десктопної, блокування ботів. Для тестувальника це палиця на два кінці: автотест із дефолтним User-Agent бібліотеки (curl/…, PostmanRuntime/…) може отримати іншу відповідь, ніж реальний браузер; підміна того самого заголовка навпаки дає «мобільну» гілку без пристрою.

    Але не все підміняється. Fetch перелічує forbidden request-header — заголовки, яких код задати не може: серед них Cookie, Host, Origin, Referer, Connection, Content-Length, Date, TE, Transfer-Encoding, а також усе, що починається з proxy- чи sec-. User-Agent у цьому переліку немає — і саме тому підміна працює: браузер підставляє власне значення лише тоді, коли в списку заголовків його ще немає.

    Найчастіший практичний ужиток — фікстура автентифікації: замість логіну через UI тест один раз бере токен і додає його в заголовок наступних запитів.

    // playwright.config.ts — усі запити тесту йдуть уже з токеном
    export default defineConfig({
      use: {
        extraHTTPHeaders: {
          Authorization: `Bearer ${process.env.API_TOKEN}`,
          Accept: 'application/json',
        },
      },
    });

    Наша практика (не канон). Канонічного джерела під це немає: для тесту заголовки — найдешевший важіль керування запитом. Підмінивши один рядок, тест логіниться без інтерфейсу, просить інший формат відповіді або вдає інший клієнт — і це майже завжди дешевше, ніж відтворювати ту саму умову клацанням.

    Тіло: необовʼязкова частина після порожнього рядка

    Тіло (body) несе власне дані. У запиті воно передає інформацію на сервер, у відповіді — запитані дані або пояснення, чому запит не виконано. Що саме в ньому лежить і скільки його — кажуть Content-Type і Content-Length; без них приймач не знає ні формату, ні межі даних.

    Тіло є не в кожному повідомленні. Із запитів його мають POST, PUT і PATCH. З відповідей тіла може не бути в тих, що відповідають на запит без потреби у вмісті: MDN наводить прикладами 201 Created і 204 No Content. Для 204 це означення — тіла немає ніколи, значущі лише заголовки. Окремий випадок — відповідь на HEAD, де заборона нормативна. Практичний наслідок: спроба розпарсити JSON із 204 впаде, і це не баг сервера. Семантику самих кодів розбирає наступна глава — «HTTP статус-коди».

    Межа «query проти тіла» і multipart

    І рядок запиту (query), і тіло передають дані серверу — межа проходить не по смаку, а по трьох речах. Query — плоскі пари «ключ-значення» в URL, видимі всім, хто бачить адресу, і обмежені довжиною. Тіло — довільна структура (JSON, форма, файли) поза URL, з лімітом на порядки більшим.

    Цифри тут не з повітря. Специфікація зверху довжину URL не обмежує, зате задає нижню межу підтримки: усім відправникам і отримувачам RECOMMENDED тримати щонайменше 8000 октетів. Дефолти серверів того самого порядку — в Apache LimitRequestLine 8190 байтів (а request-line це метод, URI та версія, тож ліміт покриває і query), у nginx рядок запиту не може перевищити один буфер із large_client_header_buffers 4 8k, інакше клієнт отримує 414. Тіло має власний ліміт: LimitRequestBody за замовчуванням 1073741824 байти. Тобто «великі дані — тілом» це не стильова порада, а різниця лімітів. Будову URL і кодування символів розбирає глава «URL і кодування».

    Коли у формі є файл, звичайного application/x-www-form-urlencoded замало — тут працює multipart/form-data. Тіло розбивається на частини (parts), кожна зі своїми міні-заголовками, а розділяє їх унікальний рядок-розділювач (boundary), оголошений у Content-Type. Частина з файлом додатково має filename і власний Content-Type.

    POST /api/upload HTTP/1.1
    Content-Type: multipart/form-data; boundary=abc123
    
    --abc123
    Content-Disposition: form-data; name="title"
    
    Some report name
    --abc123
    Content-Disposition: form-data; name="file"; filename="report.pdf"
    Content-Type: application/pdf
    
    %PDF-1.4 ... (бінарний вміст файлу) ...
    --abc123--

    Роздільник — це два дефіси плюс значення boundary із заголовка, а завершальний додає ще два дефіси в кінці. Вимога унікальності нормативна: роздільник MUST NOT траплятися всередині жодної з частин — ні окремим рядком, ні як префікс рядка. Сам параметр — єдиний обовʼязковий для multipart, довжиною 1–70 символів і не може закінчуватися пробілом. Складене вручну тіло легко зіпсувати саме на boundary чи заголовках частин, тому у Playwright і HTTP-клієнтах передавайте файл обʼєктом і хай бібліотека збере його сама.

    Наша практика (не канон). Джерела під це немає, але правило стійке: секрети йдуть тілом, бо query осідає в адресному рядку, історії браузера, логах сервера й реферерах. Токен у query-параметрі — готова знахідка для security-репорту.

    Безстановість: увесь контекст їде в кожному повідомленні

    HTTP визначений як безстановий (stateless) протокол: семантику кожного запиту можна зрозуміти ізольовано, і сервер не має припускати звʼязок між двома запитами на одному зʼєднанні. Те саме обмеження є в REST: кожен запит містить усю потрібну для його розуміння інформацію й не спирається на збережений на сервері контекст — стан сесії лишається на клієнті. Мотив прагматичний: якщо сервер не мусить памʼятати клієнтів, будь-який із десятка однакових серверів обробить будь-який запит.

    Уточнення, без якого виходить плутанина: безстановий тут протокол, а не застосунок. Стан у застосунку є майже завжди — просто він живе в базі й у тому, що клієнт приносить із кожним запитом. А приносить він його рівно двома частинами повідомлення, які ми щойно розібрали: заголовками й тілом. Найпоширеніший механізм памʼяті — кукі: сервер ставить їх заголовком Set-Cookie, а браузер повертає на наступних запитах. Альтернатива — токен у Authorization, який клієнт зберігає й додає сам.

    Для тестів це і полегшення, і пастка. Полегшення — бо ізольований запит легко повторити: підготувати стан одним замість проходу майстра з десяти екранів. Пастка — бо «залогінитися один раз» на рівні протоколу не існує: кожен запит має нести автентифікацію сам. Модель клієнт-сервер загалом розбирає глава «Клієнт-сервер і як працює веб».

    Версія протоколу змінює подання, а не семантику

    До HTTP/2 повідомлення текстові й читабельні очима; у HTTP/2 їх загортають у бінарні кадри — читати важче, а логічна модель лишається тією самою. У HTTP/2 стартового рядка як окремого рядка немає взагалі: керівні дані передають псевдозаголовками з двокрапкою на початку — :method, :scheme, :authority, :path у запиті й :status у відповіді. HTTP/3 уживає такі самі за призначенням поля й прямо каже про себе: способу передати версію чи пояснювальну фразу зі статус-рядка HTTP/1.1 він не визначає. Читати це як «а HTTP/2 щось таке має» не можна — версію RFC 9113 формулює теж, просто неявно: окремого індикатора в повідомленні немає, і запити з відповідями «implicitly have a protocol version of "2.0"» (§8.3.1 і §8.3.2). Різниця лише в другій половині: пояснювальної фрази RFC 9113 не згадує жодного разу, тож для HTTP/2 її відсутність — вивід із семантики HTTP, а не цитата зі специфікації.

    Головне: HTTP/2 — не нова семантика, а оптимізоване подання тієї самої. Методи, статус-коди й заголовки ті самі; змінюється спосіб, у який вони їдуть зʼєднанням, і саме зʼєднання намагаються перевикористати (keep-alive, а в HTTP/2 ще й мультиплексування). Тому переїзд на HTTP/2 не зачіпає тести на методи, коди й заголовки — змінюється транспортне подання, а не контракт. Бінарний фреймінг, стиснення заголовків і решту механіки розбирає глава «HTTP/2 і HTTP/3: еволюція протоколу».

    Типові помилки

    Виглядає як «безпечний метод нічого не зіпсує» — а насправді «безпечний» описує семантику, яку замовляє клієнт, і не забороняє реалізації мати побічні ефекти. GET, що видаляє, технічно можливий; саме тому це баг контракту.

    Виглядає як «DELETE не ідемпотентний, бо другий виклик дає 404» — а насправді ідемпотентність про стан сервера, а не про код відповіді. Стан після другого виклику той самий: ресурсу немає.

    Виглядає як «мій PATCH ідемпотентний, я ж шлю той самий JSON» — а насправді ідемпотентність тут властивість методу, і специфікація її від PATCH не вимагає. Конкретний запит може виявитися ідемпотентним, але будувати на цьому ретрай не можна.

    Виглядає як «сервер загубив розмір файлу» — а насправді Content-Length у відповіді на HEAD сервер MAY пропустити. Асерт на розмір без перевірки наявності заголовка — джерело флаку, а не знахідка.

    Виглядає як «сервер не приймає валідний JSON — значить, 400» — а насправді на непідтримуваний формат тіла нормативний код 415, і 400 тут відступ від специфікації, який варто назвати в баг-репорті.

    Виглядає як «зайвий OPTIONS у панелі — баг фронтенду» — а насправді це CORS preflight, обовʼязковий для непростих крос-оріджин запитів.

    Виглядає як «тест бачить те саме, що браузер» — а насправді з іншим User-Agent сервер має право віддати іншу гілку поведінки.

    Підсумок

    • Запит і відповідь мають одну будову: стартовий рядок, заголовки, порожній рядок, тіло. Порожній рядок — частина синтаксису, а не форматування.
    • Метод описує намір клієнта, а не гарантує поведінку реалізації. Тому «GET, який видаляє» — баг контракту, а не особливість.
    • Ідемпотентність — про стан сервера після N однакових викликів, а не про однаковість відповідей. DELETE із 404 на другий виклик ідемпотентний.
    • Заголовки — метадані, що уточнюють семантику повідомлення: формат вмісту, автентифікація, опис клієнта. Частину з них код задати не може взагалі.
    • Тіло необовʼязкове, і його межу задають Content-Type та Content-Length; частина відповідей іде без тіла свідомо. Секрети — тілом, ніколи в рядку запиту.

    Можливі питання

    • З яких частин складається HTTP-повідомлення? Перевіряють не завчений список, а розуміння, що будова однакова для запиту й відповіді й що порожній рядок несе синтаксичну роль.
    • Що таке безпечний метод і чому GET, який змінює дані, — це баг? Тут чути, чи кандидат каже «без побічних ефектів» (спрощення), чи «семантика лише для читання з погляду клієнта». Плюс балів — за наслідок: префетч і краулери викличуть такий без наміру шкодити.
    • Що таке ідемпотентність і чому DELETE ідемпотентний, якщо другий раз повертає 404? Класична перевірка на плутанину «стан сервера проти тіла відповіді». Гарна відповідь дає перелік і пояснює, чому POST із нього випадає.
    • Чим PUT відрізняється від PATCH? Цікавить не словник, а : PUT замінює цілком, тож непередані поля втрачаються.
    • Коли дані передавати в рядку запиту, а коли тілом? Дивляться на три критерії: видимість, обмеження довжини, структура даних. Згадка про порядок 8 кБ на рядок запиту показує, що людина бачила реальні 414.
    • Чим Content-Type відрізняється від Accept? Питання на уважність до напрямку: що вже лежить у тілі проти того, що клієнт хоче отримати. Сильна відповідь додає код відмови 415.
    • Навіщо потрібен HEAD? Перевіряють, чи розуміє кандидат, що тіла у відповіді бути не може, а заголовки гарантовані не всі. Найкращий фінал — пастка з Content-Length.

    Джерела

    Одна структура на запит і на відповідь

    • MDN — HTTP messages — два типи повідомлень, спільна будова, голова проти тіла, склад request-line і status-line, формат заголовка в HTTP/1.x.
    • RFC 9110 — HTTP Semantics — заголовки як поля, що передаються перед вмістом повідомлення.
    • RFC 9112 — HTTP/1.1 (message syntax) — клієнту SHOULD ігнорувати пояснювальну фразу: це ненадійний канал.

    Метод: намір, а не гарантія

    • MDN — HTTP request methods — метод як перший елемент стартового рядка, три наскрізні властивості, матриця безпечності/ідемпотентності/кешованості, умовна кешованість POST і PATCH.
    • RFC 9110 — HTTP Semantics — означення безпечного методу через семантику «лише читання», дозвіл на побічні ефекти, мета поділу (spiders, префетч), перелік безпечних методів.

    Розбір методів

    • RFC 9110 — HTTP Semantics — семантика GET, POST, PUT, DELETE, OPTIONS; заборона тіла у відповіді на HEAD і дозвіл пропустити Content-Length; тіло в GET без загальновизначеного значення.
    • MDN — HTTP request methods — довідник методів і формати тіла PATCH (RFC 6902, RFC 7396) поруч із власним частковим JSON.
    • RFC 5789 — PATCH Method for HTTP — різниця тіл: змінена версія ресурсу в PUT проти набору інструкцій у PATCH.
    • MDN — Cross-Origin Resource Sharing (CORS) — preflight як обовʼязкове опитування сервера методом OPTIONS.
    • OWASP WSTG — 4.2.6 Test HTTP Methods (WSTG-CONF-06) — перелік з OPTIONS перевіряють фактичними запитами; TRACE як віддзеркалення повідомлення й ризик крадіжки облікових даних.

    Ідемпотентність: про стан сервера, а не про відповідь

    • RFC 9110 — HTTP Semantics — означення ідемпотентності через ефект на сервері, перелік (PUT, DELETE і безпечні методи), безпечність повторів після збою.
    • MDN — HTTP request methods — матриця ідемпотентності, приклади POST і PATCH, розведення ідемпотентності й кешованості.
    • MDN — Idempotent (Glossary) — поіменний перелік неідемпотентних методів разом із CONNECT.
    • RFC 5789 — PATCH Method for HTTPPATCH не є ані безпечним, ані ідемпотентним; конкретний запит можна зробити ідемпотентним.

    Заголовки: метадані повідомлення

    • RFC 9110 — HTTP SemanticsContent-Type як медіа-тип тіла, Content-Length як розмір у байтах, Accept і ваги q (зокрема q=0 як відмова й три цифри після коми), 415 для непідтримуваного формату.
    • MDN — HTTP messages — заголовки як метадані між стартовим рядком і тілом.

    Заголовки, якими тест керує запитом

    • RFC 7617 — The 'Basic' HTTP Authentication Scheme — склад Basic, роль першої двокрапки, base64 як кодування й SHOULD NOT без TLS, пари 401/WWW-Authenticate і 407/Proxy-Authenticate.
    • RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage — форма запиту зі схемою Bearer.
    • RFC 9110 — HTTP Semantics401 із WWW-Authenticate як виклик до входу; User-Agent як опис клієнта, за яким сервери підлаштовують відповіді.
    • WHATWG Fetch Standard — перелік forbidden request-header і правило, за яким браузер додає User-Agent лише за відсутності власного значення.
    • Playwright — API testing — токен, отриманий один раз і підкладений у заголовки наступних запитів, замість логіну через UI.

    Тіло: необовʼязкова частина після порожнього рядка

    • MDN — HTTP messages — тіло як носій даних у запиті й відповіді, тіло лише в PATCH, POST і PUT, відповіді без тіла (201, 204).
    • RFC 9110 — HTTP SemanticsContent-Type і Content-Length як формат і межа даних; заборона тіла у відповіді на HEAD.
    • MDN — HTTP response status codes204 No Content: тіла немає, заголовки значущі.

    Межа «query проти тіла» і multipart

    Безстановість: увесь контекст їде в кожному повідомленні

    Версія протоколу змінює подання, а не семантику

    • MDN — HTTP messages — текстові повідомлення до HTTP/2 і бінарне обгортання в HTTP/2; заміна стартового рядка псевдозаголовками.
    • RFC 9113 — HTTP/2 — псевдозаголовки :method, :scheme, :authority, :path, :status; неявна версія протоколу «2.0» для запитів (§8.3.1) і відповідей (§8.3.2); та сама семантика в іншому поданні.
    • RFC 9114 — HTTP/3 — ті самі за призначенням псевдозаголовки; специфікація не визначає способу передати версію чи пояснювальну фразу зі статус-рядка HTTP/1.1.
    • MDN — Connection management in HTTP/1.x зʼєднання замість встановлення нового на кожен запит.

    Пояснення

    «Поясни» працює з власним API-ключем Anthropic: запит іде з вашого браузера прямо до Anthropic.

    Свій API-ключ (BYOK)

    Вставте власний ключ Anthropic — пояснення працюватиме на реальній моделі. Ключ зберігається лише у вашому браузері (localStorage), нікуди не надсилається, крім api.anthropic.com, і не логується.