Пошук уроків, статей та іншого контенту
Навчитеся складати URL і розрізняти методи GET, POST, PUT, PATCH та DELETE за їхнім призначенням.
URL (Uniform Resource Locator) — це адреса ресурсу в мережі. За URL браузер розуміє, куди потрібно надіслати HTTP-запит.
Приклад:
https://example.com:443/products/42?category=books&sort=price#reviewsURL складається з кількох частин:
https — протокол;
example.com — доменне ім’я;
443 — порт;
/products/42 — шлях до ресурсу;
?category=books&sort=price — рядок запиту;
#reviews — фрагмент сторінки.
Не всі частини URL є обов’язковими. Наприклад:
https://example.com/productsНайчастіше в браузері використовують:
http — незахищене HTTP-з’єднання;
https — HTTP поверх захищеного з’єднання.
У сучасних застосунках майже завжди потрібно використовувати https.
Домен вказує, з яким сервером потрібно зв’язатися:
example.comПорт уточнює, на якому мережевому порту сервер приймає запити:
https://example.com:8443Стандартні порти зазвичай не вказують явно:
http використовує порт 80;
https використовує порт 443.
Шлях описує конкретний ресурс на сервері:
/users
/users/15
/products/42/reviewsЧасто число в шляху є ідентифікатором ресурсу:
/users/15Тут 15 — ідентифікатор користувача.
Рядок запиту починається символом ? і містить параметри у форматі ключ=значення:
/products?category=books&sort=priceУ цьому прикладі є два параметри:
category має значення books;
sort має значення price.
Пари параметрів розділяються символом &.
Рядок запиту часто використовують для:
фільтрації;
сортування;
пошуку;
пагінації;
передачі необов’язкових параметрів.
Фрагмент починається символом #:
/docs#installationВін зазвичай вказує на частину вже завантаженої сторінки. Фрагмент не надсилається серверу в HTTP-запиті.
У браузері фрагмент може використовуватися для переходу до елемента з відповідним id:
<h2 id="installation">Встановлення</h2>Після переходу на /docs#installation браузер прокрутить сторінку до цього заголовка.
Для роботи з URL у браузері є вбудований клас URL.
const address = new URL(
"https://example.com/products/42?category=books&sort=price#reviews"
);
console.log(address.protocol); // "https:"
console.log(address.hostname); // "example.com"
console.log(address.port); // ""
console.log(address.pathname); // "/products/42"
console.log(address.search); // "?category=books&sort=price"
console.log(address.hash); // "#reviews"
console.log(address.searchParams.get("category")); // "books"
console.log(address.searchParams.get("sort")); // "price"
address.searchParams.set("page", "2");
address.searchParams.delete("sort");
console.log(address.toString());
// https://example.com/products/42?category=books&page=2#reviewsURL може бути абсолютним або відносним:
const absoluteUrl = new URL("https://example.com/users");
const relativeUrl = new URL("/users", window.location.origin);
console.log(absoluteUrl.href);
console.log(relativeUrl.href);window.location.origin містить протокол, домен і порт поточної сторінки, наприклад:
https://my-site.exampleДля безпечного створення рядка запиту використовуйте URLSearchParams:
const params = new URLSearchParams();
params.set("q", "javascript у браузері");
params.set("page", "1");
const url = `/search?${params.toString()}`;
console.log(url);
// /search?q=javascript+у+браузері&page=1Це краще, ніж складати рядок вручну, оскільки спеціальні символи буде закодовано автоматично.
Коли браузер звертається до сервера, він надсилає HTTP-запит. Запит може містити:
метод;
URL;
заголовки;
тіло запиту.
Приклад запиту:
GET /products/42 HTTP/1.1
Host: example.com
Accept: application/jsonСервер обробляє запит і повертає HTTP-відповідь. Відповідь містить:
статус-код;
заголовки;
тіло відповіді.
Наприклад:
HTTP/1.1 200 OK
Content-Type: application/json
{"id":42,"name":"Книга"}GET використовують для отримання даних.
Приклади:
GET /users
GET /users/15
GET /products?category=booksGET-запит:
не повинен змінювати дані на сервері;
може містити параметри в URL;
зазвичай не має тіла;
можна повторити без створення додаткових змін.
У JavaScript запит GET можна виконати за допомогою fetch:
async function loadProducts() {
const response = await fetch("/api/products?category=books");
if (!response.ok) {
throw new Error(`Помилка HTTP: ${response.status}`);
}
const products = await response.json();
console.log(products);
}
loadProducts().catch((error) => {
console.error(error);
});fetch повертає об’єкт Response. Метод response.json() читає тіло відповіді та перетворює JSON на JavaScript-значення.
POST використовують для створення нового ресурсу або виконання дії на сервері.
Приклади:
POST /users
POST /orders
POST /messagesДані зазвичай передають у тілі запиту:
async function createUser() {
const response = await fetch("/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Олена",
email: "olena@example.com"
})
});
if (!response.ok) {
throw new Error(`Помилка HTTP: ${response.status}`);
}
const createdUser = await response.json();
console.log(createdUser);
}Заголовок Content-Type: application/json повідомляє серверу, що тіло запиту містить JSON.
JSON.stringify перетворює JavaScript-об’єкт на текст JSON:
const user = {
name: "Олена",
age: 25
};
const json = JSON.stringify(user);
console.log(json);
// {"name":"Олена","age":25}PUT використовують для повної заміни ресурсу.
Наприклад:
PUT /users/15Тіло запиту може містити повний опис користувача:
async function replaceUser() {
const response = await fetch("/api/users/15", {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Олена Коваль",
email: "olena.koval@example.com",
role: "user"
})
});
if (!response.ok) {
throw new Error(`Помилка HTTP: ${response.status}`);
}
const user = await response.json();
console.log(user);
}Якщо ресурс має поля name, email і role, то під час повної заміни бажано передати всі ці поля.
Важлива властивість PUT: повторення однакового запиту зазвичай приводить до того самого результату. Такий запит називають ідемпотентним.
PATCH використовують для часткового оновлення ресурсу.
Наприклад, якщо потрібно змінити лише ім’я користувача:
async function updateUserName() {
const response = await fetch("/api/users/15", {
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Олена Коваль"
})
});
if (!response.ok) {
throw new Error(`Помилка HTTP: ${response.status}`);
}
const updatedUser = await response.json();
console.log(updatedUser);
}Різниця між PUT і PATCH:
PUT — замінити ресурс повністю;
PATCH — змінити лише окремі поля.
Точна поведінка залежить від API. Перед використанням методу потрібно перевірити документацію конкретного сервера.
DELETE використовують для видалення ресурсу.
DELETE /users/15Приклад:
async function deleteUser() {
const response = await fetch("/api/users/15", {
method: "DELETE"
});
if (!response.ok) {
throw new Error(`Помилка HTTP: ${response.status}`);
}
console.log("Користувача видалено");
}Сервер може відповісти:
200 OK і повернути видалений ресурс;
202 Accepted, якщо видалення буде виконано пізніше;
204 No Content, якщо відповідь не містить тіла.
Якщо сервер повернув 204, не потрібно викликати response.json(), адже тіло відповіді порожнє.
GET — отримати ресурс;
POST — створити ресурс або виконати дію;
PUT — повністю замінити ресурс;
PATCH — частково оновити ресурс;
DELETE — видалити ресурс.
Приклад роботи з одним ресурсом:
GET /api/tasks/7 отримати завдання
POST /api/tasks створити завдання
PUT /api/tasks/7 повністю замінити завдання
PATCH /api/tasks/7 змінити частину завдання
DELETE /api/tasks/7 видалити завданняПісля запиту сервер повертає статус-код.
Найпоширеніші коди:
200 OK — запит успішний;
201 Created — ресурс створено;
202 Accepted — запит прийнято для подальшої обробки;
204 No Content — успішно, але тіло відповіді відсутнє;
400 Bad Request — некоректний запит;
401 Unauthorized — потрібна автентифікація;
403 Forbidden — доступ заборонено;
404 Not Found — ресурс не знайдено;
409 Conflict — конфлікт даних;
500 Internal Server Error — помилка на сервері.
Властивість response.ok має значення true для статусів від 200 до 299.
Важливо: fetch не вважає HTTP-помилки винятком автоматично. Наприклад, відповідь зі статусом 404 зазвичай все одно поверне об’єкт Response. Тому статус потрібно перевіряти самостійно:
const response = await fetch("/api/tasks/999");
if (!response.ok) {
throw new Error(`Сервер повернув статус ${response.status}`);
}Заголовки передають додаткову інформацію про запит:
const response = await fetch("/api/profile", {
headers: {
"Accept": "application/json",
"Authorization": "Bearer token"
}
});Поширені заголовки:
Accept — який формат відповіді очікує клієнт;
Content-Type — формат тіла запиту;
Authorization — дані для автентифікації.
Для JSON-запиту зазвичай використовують:
{
"Content-Type": "application/json"
}Тіло запиту передають через властивість body. Для JavaScript-об’єкта його потрібно перетворити на JSON:
body: JSON.stringify({
title: "Вивчити HTTP"
})Нижче наведено приклад, який можна виконати в консолі браузера. Він створює URL і об’єкти Request, не надсилаючи реальних запитів на сервер.
const apiUrl = new URL("/api/tasks", window.location.origin);
apiUrl.searchParams.set("completed", "false");
apiUrl.searchParams.set("page", "1");
const getRequest = new Request(apiUrl, {
method: "GET",
headers: {
"Accept": "application/json"
}
});
const postRequest = new Request(apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
title: "Вивчити методи HTTP",
completed: false
})
});
const patchUrl = new URL("/api/tasks/7", window.location.origin);
const patchRequest = new Request(patchUrl, {
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
completed: true
})
});
const deleteRequest = new Request(patchUrl, {
method: "DELETE"
});
console.log(getRequest.method, getRequest.url);
console.log(postRequest.method, postRequest.url);
console.log(patchRequest.method, patchRequest.url);
console.log(deleteRequest.method, deleteRequest.url);
console.log(await postRequest.clone().json());
console.log(await patchRequest.clone().json());Метод clone() потрібен тому, що тіло Request є потоком, який можна прочитати лише один раз. У реальному коді зазвичай немає потреби читати тіло запиту вручну.
Не варто видаляти або змінювати дані через URL на кшталт:
GET /delete-user?id=15Для видалення потрібно використовувати DELETE, а для створення — POST.
GET-запити можуть повторюватися через перезавантаження сторінки, кешування або переходи браузера.
Це різні частини URL:
/products/42
/products?id=42У першому випадку 42 є частиною шляху. У другому — значенням параметра id.
Небезпечно вставляти введений користувачем текст у URL без кодування:
const query = "книги та журнали";
const url = `/search?q=${query}`;Краще використовувати URLSearchParams:
const params = new URLSearchParams({
q: "книги та журнали"
});
const url = `/search?${params.toString()}`;
console.log(url);JSON.stringifyНеправильно:
body: {
name: "Олена"
}Правильно:
body: JSON.stringify({
name: "Олена"
})Content-TypeЯкщо тіло містить JSON, повідомте про це сервер:
headers: {
"Content-Type": "application/json"
}fetch автоматично обробить статус 404fetch не викидає помилку лише через статус 404 або 500. Перевіряйте response.ok:
const response = await fetch("/api/data");
if (!response.ok) {
throw new Error(`HTTP-помилка: ${response.status}`);
}Для відповіді 204 No Content не використовуйте:
await response.json();Спочатку переконайтеся, що сервер справді повернув тіло відповіді.
URL описує адресу ресурсу та складається з протоколу, домену, шляху, параметрів і фрагмента.
Шлях зазвичай ідентифікує ресурс.
Рядок запиту використовують для фільтрації, пошуку, сортування та пагінації.
GET отримує дані.
POST створює ресурс або запускає дію.
PUT повністю замінює ресурс.
PATCH змінює частину ресурсу.
DELETE видаляє ресурс.
Для роботи з URL у JavaScript використовують URL і URLSearchParams.
Для HTTP-запитів у браузері використовують fetch.
Після fetch потрібно перевіряти response.ok і враховувати статус відповіді.