Fetch API - Повний довідник опцій
Fetch API - Повний довідник опцій
Вступ та Контекст
На цей момент ми вже детально розглянули основи Fetch API: базові запити, FormData, відстеження прогресу, переривання та CORS. Але Fetch API має набагато більше можливостей через додаткові опції конфігурації.
Важливо: Більшість цих опцій використовуються рідко і потрібні лише для спеціалізованих сценаріїв. Ви можете успішно працювати з fetch, знаючи лише базові опції. Цей розділ — довідник для особливих випадків.
- Потрібно контролювати кешування
- Треба налаштувати Referer header
- Важлива валідація цілісності файлів (integrity)
- Потрібні аналітичні запити, які "переживають" закриття сторінки
Повний синтаксис Fetch
Ось всі можливі опції з їх значеннями за замовчуванням:
const response = await fetch(url, {
// Основні опції (розглянуті раніше)
method: 'GET', // POST, PUT, DELETE, PATCH
headers: {}, // об'єкт або Headers
body: undefined, // string, FormData, Blob, URLSearchParams
signal: undefined, // AbortController.signal
// Безпека та CORS
mode: 'cors', // 'same-origin', 'no-cors'
credentials: 'same-origin', // 'omit', 'include'
// Referer
referrer: 'about:client', // '' (не відправляти) або URL
referrerPolicy: 'strict-origin-when-cross-origin',
// Кешування
cache: 'default', // 'no-store', 'reload', 'no-cache', etc.
// Переадресація
redirect: 'follow', // 'error', 'manual'
// Валідація цілісності
integrity: '', // наприклад, 'sha256-abc123...'
// Keepalive
keepalive: false, // true для аналітики
// Застарілі/рідковживані
window: window, // null
})
GET, POST, PUT, DELETE, PATCHHeadersstring, FormData, Blob, URLSearchParamsAbortController для перериванняReferrer та Referrer Policy
Що таке Referer?
Referer (так, з помилкою в назві) — HTTP header, який містить URL сторінки, з якої був зроблений запит.
GET /api/data HTTP/1.1
Host: api.example.com
Referer: https://mysite.com/admin/dashboard
Навіщо? Сервер бачить, звідки прийшов запит (для аналітики, безпеки).
Проблема: Може розкривати чутливу інформацію з URL (наприклад, /admin/secret-page).
Опція referrer
Дозволяє встановити або приховати Referer:
// Не відправляти Referer взагалі
fetch('/api/data', {
referrer: '',
})
// Встановити власне значення (в межах того самого origin)
fetch('/api/data', {
referrer: 'https://mysite.com/public-page',
})
referrer тільки на URL вашого власного origin. Неможливо підробити Referer на чужий домен.// ✅ Можна (той самий origin)
fetch('/api', { referrer: 'https://mysite.com/page' })
// ❌ Буде ігноровано (інший origin)
fetch('/api', { referrer: 'https://evil.com' })
Опція referrerPolicy
Встановлює загальні правила для Referer header:
| Policy | Same-Origin | Cross-Origin | HTTPS→HTTP |
|---|---|---|---|
no-referrer | — | — | — |
no-referrer-when-downgrade | Full URL | Full URL | — |
origin | Origin only | Origin only | Origin only |
origin-when-cross-origin | Full URL | Origin only | Origin only |
same-origin | Full URL | — | — |
strict-origin | Origin only | Origin only | — |
strict-origin-when-cross-origin ⭐ | Full URL | Origin only | — |
unsafe-url | Full URL | Full URL | Full URL |
⭐ Значення за замовчуванням
Пояснення значень:
- Full URL:
https://site.com/admin/dashboard - Origin only:
https://site.com - —: не відправляти Referer
Приклад: приховування шляху від зовнішніх сайтів
// Для cross-origin відправляємо лише origin, без шляху
fetch('https://external-api.com/data', {
referrerPolicy: 'origin-when-cross-origin',
})
// Referer буде: https://mysite.com (без /admin/secret)
Приклад: повна приватність
// Ніколи не відправляти Referer
fetch('/api/data', {
referrerPolicy: 'no-referrer',
})
Mode - Контроль CORS
Опція mode контролює, чи дозволені cross-origin запити:
fetch(url, {
mode: 'cors' | 'same-origin' | 'no-cors',
})
Значення
'cors' (за замовчуванням)
Дозволяє cross-origin запити з CORS headers:
fetch('https://api.github.com/users/octocat', {
mode: 'cors', // дозволено
})
'same-origin'
Заборонює будь-які cross-origin запити:
fetch('https://external-api.com/data', {
mode: 'same-origin',
})
// ❌ TypeError: Failed to fetch
'no-cors'
Дозволяє лише "безпечні" cross-origin запити БЕЗ доступу до відповіді:
const response = await fetch('https://example.com/image.jpg', {
mode: 'no-cors',
})
console.log(response.status) // 0
console.log(await response.text()) // Помилка - доступ заборонено!
no-cors - не те, що ви думаєтеБагато розробників помилково використовують mode: 'no-cors', думаючи, що це "вимкне CORS". Насправді це робить відповідь opaque (непрозорою) — ви не можете прочитати дані!✅ Використовуйте no-cors лише для:- Завантаження ресурсів без читання (наприклад, зображення для кешування)
- Logging/Analytics запитів, де відповідь не важлива
- Отримання даних API
- Будь-яких запитів, де потрібна відповідь
Credentials - Cookies та Authentication
Контролює відправку cookies та HTTP Authentication:
fetch(url, {
credentials: 'same-origin' | 'include' | 'omit',
})
Значення
'same-origin' (за замовчуванням)
Cookies відправляються лише для same-origin запитів:
// ✅ Cookies відправляються
fetch('/api/profile')
// ❌ Cookies НЕ відправляються
fetch('https://external-api.com/data')
'include'
Завжди відправляти cookies (навіть cross-origin):
fetch('https://api.mybackend.com/profile', {
credentials: 'include',
})
Сервер має відповісти:
Access-Control-Allow-Origin: https://mysite.com
Access-Control-Allow-Credentials: true
'omit'
Ніколи не відправляти cookies (навіть same-origin):
fetch('/api/public-data', {
credentials: 'omit', // Без cookies
})
Приклад: Авторизований API запит
async function getUUserProfile() {
const response = await fetch('https://api.myapp.com/user/profile', {
credentials: 'include', // Відправити session cookie
headers: {
Accept: 'application/json',
},
})
if (!response.ok) {
throw new Error('Not authenticated')
}
return response.json()
}
Cache - Контроль HTTP кешування
Керує взаємодією з HTTP-кешем браузера:
fetch(url, {
cache: 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached',
})
Значення
| Режим | Опис | Коли використовувати |
|---|---|---|
default | Стандартне HTTP кешування | 99% випадків |
no-store | Не кешувати запит і відповідь | Чутливі дані |
reload | Ігнорувати кеш, але оновити його | "Примусове оновлення" |
no-cache | Валідувати кеш, потім використати | Актуальні дані |
force-cache | Використати кеш (навіть застарілий) | Офлайн режим |
only-if-cached | Тільки кеш, помилка якщо немає | Повний офлайн |
Приклади
Завжди свіжі дані (без кешу)
fetch('/api/stock-prices', {
cache: 'no-store', // Ніколи не кешувати
})
Примусове оновлення (hard reload)
fetch('/api/config', {
cache: 'reload', // Ігнорувати кеш, оновити його
})
Офлайн-режим (використовувати кеш)
fetch('/api/articles', {
cache: 'force-cache', // Використати кеш, навіть якщо застарілий
}).catch(() => {
console.log('Немає інтернету, використано кеш')
})
Redirect - Processing Переадресацій
Контролює обробку HTTP redirects (301, 302, 307, 308):
fetch(url, {
redirect: 'follow' | 'error' | 'manual',
})
Значення
'follow' (за замовчуванням)
Автоматично слідувати redirects:
fetch('http://example.com/old-url', {
redirect: 'follow',
})
// Автоматично перейде на новий URL
'error'
Генерувати помилку при redirect:
fetch('http://example.com/old-url', {
redirect: 'error',
})
// TypeError: Failed to fetch (якщо є redirect)
'manual'
Дозволяє обробляти redirects вручну:
const response = await fetch('http://example.com/old-url', {
redirect: 'manual',
})
if (response.type === 'opaqueredirect') {
console.log('Redirect виявлено, але не обробленосправжнього статусу немає')
// response.status === 0
// response.url === ''
}
manual?Рідко потрібно. Може бути корисно для:- Відстеження ланцюжків redirects
- Спеціальної логіки переадресацій
- Debugging redirect loops
Integrity - Перевірка цілісності
Валідує, що завантажений ресурс відповідає очікуваній контрольній сумі (hash):
fetch(url, {
integrity: 'sha256-{hash}' | 'sha384-{hash}' | 'sha512-{hash}',
})
Як це працює
- Ви знаєте заздалегідь hash файлу
- Передаєте його у
integrity - Браузер завантажує файл та обчислює hash
- Якщо hash не збігається → помилка
Приклад: Завантаження CDN скрипта
// Завантажуємо jQuery з CDN з перевіркою integrity
fetch('https://code.jquery.com/jquery-3.7.1.min.js', {
integrity: 'sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=',
})
.then((r) => r.text())
.then((code) => {
console.log('jQuery завантажено та перевірено!')
eval(code) // Безпечно, бо перевірили hash
})
.catch((error) => {
console.error('Hash не збігається! Можлива модифікація файлу.')
})
Генерація hash
Онлайн: Використовуйте SRI Hash Generator
Командний рядок:
# Для файлу
curl https://code.jquery.com/jquery-3.7.1.min.js | openssl dgst -sha256 -binary | openssl base64 -A
# Результат: sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=
integrity — це реалізація SRI специфікації. Це особливо важливо для:- Завантаження скриптів з CDN
- Гарантування, що файли не змінені
- Захисту від компрометації CDN
Keepalive - Запити після закриття сторінки
Дозволяє запиту "пережити" закриття сторінки:
fetch(url, {
keepalive: true,
})
Проблема
Коли користувач закриває вкладку, браузер скасовує всі активні запити:
window.addEventListener('unload', () => {
fetch('/analytics', {
method: 'POST',
body: JSON.stringify({ event: 'page_close' }),
})
// ❌ Запит буде скасовано!
})
Рішення: keepalive
window.addEventListener('unload', () => {
fetch('/analytics', {
method: 'POST',
body: JSON.stringify({ event: 'page_close' }),
keepalive: true, // ✅ Запит завершиться навіть після закриття
})
})
Обмеження
- Розмір: Максимум 64KB для тіла запиту
- Множинні запити: Загальний ліміт 64KB для всіх keepalive зараз
- Відповідь: Ви не можете прочитати відповідь (сторінка вже закрита)
Приклад: Аналітика відвідувань
class Analytics {
constructor() {
this.events = []
// Відправляти при закритті сторінки
window.addEventListener('beforeunload', () => {
this.flush()
})
// Або кожні 30 секунд
setInterval(() => this.flush(), 30000)
}
track(eventName, data) {
this.events.push({
event: eventName,
data,
timestamp: Date.now(),
})
// Якщо багато подій, відправити зараз
if (this.events.length >= 10) {
this.flush()
}
}
flush() {
if (this.events.length === 0) return
const payload = JSON.stringify(this.events)
// Перевірка ліміту 64KB
if (new Blob([payload]).size > 64 * 1024) {
console.warn('Payload занадто великий для keepalive')
return
}
fetch('/api/analytics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: payload,
keepalive: true,
})
this.events = []
}
}
// Використання
const analytics = new Analytics()
analytics.track('page_view', { url: location.href })
analytics.track('button_click', { button: 'signup' })
navigator.sendBeacon():window.addEventListener('beforeunload', () => {
const data = JSON.stringify({ event: 'page_close' })
navigator.sendBeacon('/analytics', data)
})
- Спеціально розроблений для аналітики
- Автоматично keepalive
- Простіший API
- Кращесь гарантії доставки
Підсумки
Fetch API має багато опцій для тонкого налаштування:
Referrer Control
{
referrer: '', // Приховати
referrerPolicy: 'no-referrer'
}
✅ Для приватності та безпеки ✅ Приховання внутрішньої структури URL
Security & CORS
{
mode: 'same-origin',
credentials: 'include'
}
✅ Контроль cross-origin запитів ✅ Керування cookies
Caching
{
cache: 'no-store', // no cache
cache: 'reload', // обійти кеш
cache: 'force-cache' // offline
}
✅ Контроль свіжості даних ✅ Офлайн режим
Integrity & Keepalive
{
integrity: 'sha256-abc...',
keepalive: true
}
✅ Валідація файлів з CDN ✅ Аналітика при закритті
Швидка довідка опцій
| Опція | Значення за замовчуванням | Основні альтернативи |
|---|---|---|
method | 'GET' | POST, PUT, DELETE, PATCH |
headers | {} | Об'єкт або Headers instance |
body | undefined | string, FormData, Blob |
mode | 'cors' | 'same-origin', 'no-cors' |
credentials | 'same-origin' | 'include', 'omit' |
cache | 'default' | 'no-store', 'reload', 'no-cache' |
redirect | 'follow' | 'error', 'manual' |
referrer | 'about:client' | '' (не відправляти), URL |
referrerPolicy | 'strict-origin-when-cross-origin' | 'no-referrer', 'origin' |
integrity | '' | 'sha256-...', 'sha384-...' |
keepalive | false | true |
signal | undefined | AbortController.signal |
Коли використовувати рідкісні опції
✅ referrerPolicy:
- Захист приватних URL від витоку
- Безпека admin-панелей
✅ cache: 'no-store':
- Фінансові дані
- Персональна інформація
- Реал-тайм pricing
✅ integrity:
- Завантаження з CDN
- Критичні безпекові скрипти
✅ keepalive:
- Аналітика відвідувань
- Логування помилок при закритті
- A/B тестування metrics
❌ Не використовувати без потреби:
mode: 'no-cors'(майже ніколи не потрібен)redirect: 'manual'(складна обробка)- Надто агресивний кешинг (
force-cache)
Більшість проектів чудово працюють з базовими опціями (method, headers, body, signal). Використовуйте розширені опції лише коли є конкретна потреба, а не "на всяк випадок".
Додаткові ресурси
- MDN: Fetch API — повна документація
- Fetch Standard — офіційна специфікація
- MDN: Request — інтерфейс Request
- Referrer Policy Spec — специфікація Referrer Policy
- Subresource Integrity — SRI специфікація
CORS - Запити між різними джерелами
Розберіть механізм CORS, safe та unsafe запити, preflight перевірки, credentials та налаштування сервера для cross-origin запитів
URL Objects - Робота з посиланнями
Навіщо потрібен клас URL, як розбирати адреси на частини, керувати query-параметрами через URLSearchParams та правильно кодувати символи