Станом на зараз ми вже дещо знаємо про fetch
.
Розгляньмо решту API, щоб охопити всі його можливості.
Зверніть увагу: більшість з цих опцій використовуються рідко. Ви можете пропустити цей розділ і все одно без проблем користуватися fetch
.
Тим не менш, корисно знати, що може робити fetch
, тому якщо виникне така необхідність, завжди можна повернутись до цієї статті і розібратись детальніше.
Ось повний список всіх можливих опцій fetch
з їх типовими значеннями (альтернативи в коментарях):
let promise = fetch(url, {
method: "GET", // POST, PUT, DELETE та інші
headers: {
// значення цього заголовку зазвичай встановлюється автоматично,
// залежно від тіла запиту
"Content-Type": "text/plain;charset=UTF-8"
},
body: undefined // string, FormData, Blob, BufferSource або URLSearchParams
referrer: "about:client", // або "", щоб не посилати заголовок Referer,
// або URL з поточного джерела
referrerPolicy: "strict-origin-when-cross-origin", // no-referrer-when-downgrade, no-referrer, origin, same-origin...
mode: "cors", // same-origin, no-cors
credentials: "same-origin", // omit, include
cache: "default", // no-store, reload, no-cache, force-cache або only-if-cached
redirect: "follow", // manual, error
integrity: "", // контрольна сума, наприклад "sha256-abcdef1234567890"
keepalive: false, // true
signal: undefined, // AbortController, щоб перервати запит
window: window // null
});
Перелік вражає, чи не так?
Ми повністю висвітлили method
, headers
та body
у главі Fetch.
Опція signal
висвітлена у главі Fetch: Переривання.
Тепер розгляньмо решту можливостей.
referrer, referrerPolicy
Ці опції вказують, як fetch
встановлює HTTP-заголовок Referer
.
Зазвичай цей заголовок встановлюється автоматично і містить адресу сторінки, з якої був зроблений запит. У більшості сценаріїв він взагалі не важливий, іноді, з метою безпеки, є сенс видалити або скоротити його.
Опція referrer
дозволяє задати будь-який Referer
(в межах поточного джерела) або видалити його..
Щоб не надсилати Referer
, задайте порожній рядок:
fetch('/page', {
referrer: "" // немає заголовку Referer
});
Щоб встановити іншу URL-адресу в межах поточного джерела:
fetch('/page', {
// припускаючи, що ми на сторінці https://javascript.info
// ми можемо задати будь-який заголовок Referer, але тільки в межах поточного джерела
referrer: "https://javascript.info/anotherpage"
});
Опція referrerPolicy
задає загальні правила для Referer
..
Запити поділяються на 3 типи:
- Запит на те ж джерело.
- Запит на інше джерело.
- Запит з HTTPS на HTTP (з безпечного на небезпечний протокол).
На відміну від опції referrer
, яка дозволяє задати конкретне значення Referer
, referrerPolicy
вказує браузеру загальні правила для кожного типу запиту.
Можливі значення описані у Referrer Policy specification:
"strict-origin-when-cross-origin"
– для запитів до однакового джерела надсилати повнийReferer
, для запитів між різними джерелами надсилати лише джерело, якщо це не HTTPS→HTTP запит, тоді нічого не надсилати."no-referrer-when-downgrade"
– типове значення: повнийReferer
надсилається завжди, хіба що ми не надсилаємо запит із HTTPS на HTTP (на менш безпечний протокол)."no-referrer"
– ніколи не надсилатиReferer
."origin"
– надсилати лише джерело вReferer
, а не повну URL-адресу сторінки, наприклад лишеhttp://site.com
замістьhttp://site.com/path
."origin-when-cross-origin"
– надсилати повнийReferer
для запитів до однакового джерела, але лише частину джерела для запитів між різними джерелами (як показано вище)."same-origin"
– надсилати повнийReferer
для запитів до однакового джерела, але безReferer
для запитів між різними джерелами."strict-origin"
– надсилати лише джерело, а неReferer
для HTTPS→HTTP запитів."unsafe-url"
– завжди надсилати повну URL-адресу вReferer
, навіть для HTTPS→HTTP запитів.
Ось таблиця зі всіма комбінаціями:
Значення | До того ж джерела | До іншого джерела | HTTPS→HTTP |
---|---|---|---|
"no-referrer" |
- | - | - |
"no-referrer-when-downgrade" |
full | full | - |
"origin" |
origin | origin | origin |
"origin-when-cross-origin" |
full | origin | origin |
"same-origin" |
full | - | - |
"strict-origin" |
origin | origin | - |
"strict-origin-when-cross-origin" або "" (типове значення) |
full | origin | - |
"unsafe-url" |
full | full | full |
Припустімо, у нас є зона адміністрування зі структурою URL-адреси, яка не повинна бути відома за межами сайту.
Якщо ми надсилаємо fetch
, то типово він завжди надсилає заголовок Referer
із повною URL-адресою нашої сторінки (окрім випадків, коли ми надсилаємо запит із HTTPS на HTTP, тоді без Referer
).
Наприклад, Referer: https://javascript.info/admin/secret/paths
.
Якщо ми хочемо, щоб інші веб-сайти знали лише джерело, а не URL-шлях, ми можемо задати опцію:
fetch('https://another.com/page', {
// ...
referrerPolicy: "origin-when-cross-origin" // Referer: https://javascript.info
});
Ми можемо додавати його до всіх викликів fetch
, навіть інтегрувати в JavaScript бібліотеку нашого проекту, яка відповідає за запити та використовує fetch
всередині.
Його єдина відмінність у порівнянні з типовою поведінкою полягає в тому, що для запитів до іншого джерела fetch
надсилає лише вихідну частину URL-адреси (наприклад, https://javascript.info
, без шляху). Для запитів до нашого джерела ми все ще отримуємо повний Referer
(може бути корисним для задач з налагодження).
fetch
Політика встановлення Referrer, що описана у специфікації, стосується не лише fetch
, а є більш глобальною.
Зокрема, можна встановити типову політику для всієї сторінки за допомогою HTTP-заголовка Referrer-Policy
або окремого посилання за допомогою <a rel="noreferrer">
.
mode
Опція mode
є засобом безпеки, що запобігає випадковим запитам між різними джерелами:
"cors"
– запити між різними джерелами типово дозволені, як описано в Fetch: Запити між різними джерелами,"same-origin"
– запити між різними джерелами заборонені,"no-cors"
– дозволені лише безпечні запити між різними джерелами.
Ця опція може бути корисною, якщо URL-адреса для fetch
надходить від третьої сторони, і ми хочемо, щоб “глобальний перемикач” обмежував можливість запитів між різними джерелами.
credentials
Опція credentials
визначає, чи має fetch
надсилати файли cookie та заголовки HTTP-Authorization разом із запитом.
"same-origin"
– типове значення, не надсилати запити між різними джерелами,"include"
– завжди надсилати, вимагаєAccess-Control-Allow-Credentials
від сервера іншого джерела, щоб JavaScript міг отримати доступ до відповіді, про що йдеться у главі Fetch: Запити між різними джерелами,"omit"
– ніколи не надсилати, навіть для запитів з однаковим джерелом.
cache
Типово запити fetch
використовують стандартне HTTP-кешування. Тобто він визнає заголовки Expires
і Cache-Control
, надсилає If-Modified-Since
і т.д. Так само як роблять звичайні HTTP-запити.
Опції cache
дозволяють ігнорувати HTTP-кеш або тонко налаштувати його використання:
"default"
–fetch
використовує стандартні правила HTTP-кешу та заголовки,"no-store"
– повністю ігнорувати HTTP-кеш, цей режим стане типовим, якщо ми встановимо заголовокIf-Modified-Since
,If-None-Match
,If-Unmodified -Since
,If-Match
абоIf-Range
,"reload"
– не брати результат із HTTP-кешу (якщо є), а заповнити кеш відповіддю (якщо заголовки відповіді дозволяють цю дію),"no-cache"
– створити умовний запит, якщо є кешована відповідь, і звичайний запит в іншому випадку. Заповнити HTTP-кеш відповіддю,"force-cache"
– використовувати відповідь з HTTP-кешу, навіть якщо він застарілий. Якщо в HTTP-кеші немає відповіді, зробити звичайний HTTP-запит, поводитися як зазвичай,"only-if-cached"
– використовувати відповідь з HTTP-кешу, навіть якщо він застарілий. Якщо в HTTP-кеші немає відповіді, то видати помилку. Працює лише тоді, колиmode
має значення"same-origin"
.
redirect
Зазвичай fetch
прозоро слідує HTTP-переадресаціям, таким як 301, 302 тощо.
Опція redirect
дозволяє змінити це:
"follow"
– типове значення, слідувати HTTP-переадресаціям,"error"
– помилка при HTTP-переадресації,"manual"
– дозволяє обробляти HTTP-переадресації вручну. У разі переадресації ми отримаємо спеціальний об’єкт відповіді зresponse.type="opaqueredirect"
та нульовим/порожнім статусом і більшістю інших властивостей.
integrity
Опція integrity
дозволяє перевірити, чи відповідає відповідь контрольній сумі відомій наперед.
Як описано в специфікації, хеш-функціями, що підтримуються, є SHA-256, SHA-384 і SHA-512, залежно від браузера.
Наприклад, ми завантажуємо файл і знаємо, що його контрольна сума SHA-256 дорівнює “abcdef” (справжня контрольна сума, звичайно, довша).
Ми можемо розмістити його в опції integrity
, наприклад:
fetch('http://site.com/file', {
integrity: 'sha256-abcdef'
});
Далі fetch
самостійно обчислить SHA-256 і порівняє його з нашим рядком. У разі розбіжності буде згенерована помилка.
keepalive
Опція keepalive
вказує на те, що запит має “пережити” веб-сторінку, яка його ініціювала.
Наприклад, ми збираємо статистику про те, як поточний відвідувач використовує нашу сторінку (кліки миші, фрагменти сторінки, які він переглядає), для аналізу і поліпшення користувацького досвіду.
Коли відвідувач залишає нашу сторінку – ми хотіли б зберегти дані на нашому сервері.
Для цього ми можемо використовувати подію window.onunload
:
window.onunload = function() {
fetch('/analytics', {
method: 'POST',
body: "statistics",
keepalive: true
});
};
Зазвичай, коли документ вивантажується, всі пов’язані з ним мережеві запити перериваються. Але опція keepalive
говорить браузеру виконувати запит у фоновому режимі, навіть після того, як він залишить сторінку. Отже, ця опція необхідна для успішного виконання нашого запиту.
Вона має кілька обмежень:
- Ми не можемо відправляти мегабайти: ліміт тіла для запитів
keepalive
становить 64КБ.- Якщо нам потрібно зібрати багато статистики про відвідування, ми повинні надсилати її регулярно пакетами, щоб на останній запит
onunload
не залишилося багато. - Це обмеження стосується всіх
keepalive
-запитів разом. Іншими словами, ми можемо паралельно виконувати декілька запитівkeepalive
, але сума довжин їхніх тіл не повинна перевищувати 64КБ.
- Якщо нам потрібно зібрати багато статистики про відвідування, ми повинні надсилати її регулярно пакетами, щоб на останній запит
- Ми не зможемо обробити відповідь сервера, якщо документ буде вивантажений. Тому в нашому прикладі
fetch
пройде успішно завдякиkeepalive
, але наступні функції не працюватимуть.- У більшості випадків, наприклад, при розсилці статистики, це не є проблемою, оскільки сервер просто приймає дані та зазвичай на такі запити відправляє порожню відповідь.