Пошук уроків, статей та іншого контенту
Розберете URL, компоненти адреси та перетворення між рядками й об’єктами за допомогою модуля url.
URL — це адреса ресурсу, яка складається з кількох компонентів. У Node.js модуль url допомагає:
розбирати URL-рядок на окремі частини;
змінювати протокол, хост, шлях або query-параметри;
будувати URL із відносних адрес;
перетворювати об’єкт URL назад у рядок.
У сучасному Node.js основним API є клас URL. Він відповідає стандарту WHATWG і використовується в браузерах та серверному JavaScript.
const { URL } = require('node:url');Розглянемо адресу:
https://admin:secret@example.com:8443/products/list?page=2&sort=price#detailsЇї компоненти:
https: — протокол;
admin:secret — облікові дані користувача;
example.com — доменне ім’я;
8443 — порт;
/products/list — шлях до ресурсу;
?page=2&sort=price — query-параметри;
#details — фрагмент документа.
Схематично URL має такий вигляд:
protocol://username:password@hostname:port/pathname?search#hashНе кожна адреса містить усі компоненти. Наприклад:
https://example.com/містить протокол, хост і шлях, але не має порту, облікових даних, query-параметрів або фрагмента.
URLКонструктор URL приймає рядок із повною адресою:
const { URL } = require('node:url');
const address = new URL(
'https://admin:secret@example.com:8443/products/list?page=2&sort=price#details'
);
console.log(address.protocol); // https:
console.log(address.username); // admin
console.log(address.password); // secret
console.log(address.hostname); // example.com
console.log(address.port); // 8443
console.log(address.pathname); // /products/list
console.log(address.search); // ?page=2&sort=price
console.log(address.hash); // #detailsОб’єкт URL містить такі важливі властивості:
href — повний URL у вигляді рядка;
origin — протокол, хост і порт;
protocol — протокол разом із двокрапкою;
username — ім’я користувача;
password — пароль;
hostname — ім’я хоста без порту;
host — хост разом із портом;
port — порт;
pathname — шлях;
search — query-рядок разом із символом ?;
hash — фрагмент разом із символом #;
searchParams — об’єкт для роботи з query-параметрами.
const { URL } = require('node:url');
const address = new URL('https://example.com:8080/catalog?page=3');
console.log(address.href); // https://example.com:8080/catalog?page=3
console.log(address.origin); // https://example.com:8080
console.log(address.host); // example.com:8080
console.log(address.hostname); // example.com
console.log(address.port); // 8080Якщо рядок не є коректним абсолютним URL, конструктор викидає помилку TypeError:
const { URL } = require('node:url');
try {
const address = new URL('not a valid url');
console.log(address.href);
} catch (error) {
console.error('Некоректний URL');
}Це важливо під час обробки даних від користувача: створення URL потрібно виконувати в try...catch або перевіряти в контрольованій функції.
Query-параметри зберігаються в searchParams. Це об’єкт URLSearchParams, який дозволяє отримувати, додавати, змінювати та видаляти параметри.
const { URL } = require('node:url');
const address = new URL('https://example.com/products?page=2&sort=price');
console.log(address.searchParams.get('page')); // 2
console.log(address.searchParams.get('sort')); // price
console.log(address.searchParams.has('filter')); // falseЗначення, отримані через get, завжди повертаються як рядки. Якщо параметра немає, результатом буде null.
const { URL } = require('node:url');
const address = new URL('https://example.com/products');
address.searchParams.set('page', '2');
address.searchParams.set('sort', 'price');
address.searchParams.append('tag', 'node');
address.searchParams.append('tag', 'url');
console.log(address.href);
// https://example.com/products?page=2&sort=price&tag=node&tag=urlМетоди мають різне призначення:
set(name, value) — встановлює значення; якщо параметр уже існує, замінює його;
append(name, value) — додає ще одне значення;
get(name) — повертає перше значення;
getAll(name) — повертає всі значення;
has(name) — перевіряє наявність;
delete(name) — видаляє параметр;
sort() — сортує параметри за іменами.
const { URL } = require('node:url');
const address = new URL(
'https://example.com/search?tag=node&tag=javascript'
);
console.log(address.searchParams.get('tag')); // node
console.log(address.searchParams.getAll('tag')); // [ 'node', 'javascript' ]
address.searchParams.delete('tag');
address.searchParams.set('q', 'URL у Node.js');
console.log(address.href);
// https://example.com/search?q=URL+у+Node.jsURLSearchParams автоматично кодує спеціальні символи під час формування URL.
const { URL } = require('node:url');
const address = new URL(
'https://example.com/search?q=node&page=2&pageSize=20'
);
for (const [name, value] of address.searchParams) {
console.log(`${name}: ${value}`);
}Результат:
q: node
page: 2
pageSize: 20Властивості об’єкта URL можна змінювати. Після зміни href автоматично перераховується.
const { URL } = require('node:url');
const address = new URL('https://example.com/old-path?page=1');
address.protocol = 'http:';
address.hostname = 'api.example.com';
address.pathname = '/v2/products';
address.searchParams.set('page', '2');
console.log(address.href);
// http://api.example.com/v2/products?page=2Для безпечної зміни query-параметрів краще використовувати searchParams, а не конкатенацію рядків:
const { URL } = require('node:url');
const address = new URL('https://example.com/search');
const userQuery = 'node.js & URL';
address.searchParams.set('q', userQuery);
console.log(address.href);
// https://example.com/search?q=node.js+%26+URLЯкби значення додавалося вручну:
const query = 'node.js & URL';
const address = 'https://example.com/search?q=' + query;спеціальні символи могли б порушити структуру URL. URLSearchParams виконує потрібне кодування автоматично.
Відносний URL не можна створити через new URL() без базової адреси:
const { URL } = require('node:url');
const address = new URL('/products');Такий код завершиться помилкою, оскільки /products не містить протоколу й хоста.
Для побудови відносної адреси потрібно передати другу, базову адресу:
const { URL } = require('node:url');
const base = 'https://example.com/catalog/';
const products = new URL('products', base);
const product = new URL('products/42', base);
const absolute = new URL('https://api.example.com/items', base);
console.log(products.href); // https://example.com/catalog/products
console.log(product.href); // https://example.com/catalog/products/42
console.log(absolute.href); // https://api.example.com/itemsРозташування базового шляху впливає на результат:
const { URL } = require('node:url');
console.log(new URL('details', 'https://example.com/catalog/').href);
// https://example.com/catalog/details
console.log(new URL('details', 'https://example.com/catalog').href);
// https://example.com/detailsЯкщо базовий URL закінчується на /, остання частина розглядається як директорія. Якщо / немає, остання частина вважається ім’ям ресурсу й замінюється.
Абсолютний шлях починається з / і замінює шлях базової адреси:
const { URL } = require('node:url');
const address = new URL('/login', 'https://example.com/account/settings');
console.log(address.href); // https://example.com/loginОб’єкт URL можна передати туди, де очікується рядок. Для явного перетворення використовують href або toString():
const { URL } = require('node:url');
const address = new URL('https://example.com/products');
address.searchParams.set('page', '2');
console.log(address.href);
console.log(address.toString());Обидва варіанти повертають:
https://example.com/products?page=2Властивість toJSON() також повертає URL-рядок:
const { URL } = require('node:url');
const address = new URL('https://example.com/products');
console.log(JSON.stringify(address));
// "https://example.com/products"Під час роботи з URL важливо розрізняти:
структуру URL;
значення параметрів;
кодування спеціальних символів.
Наприклад, пробіл у query-параметрі буде закодований:
const { URL } = require('node:url');
const address = new URL('https://example.com/search');
address.searchParams.set('q', 'Node.js URL');
console.log(address.search);
// ?q=Node.js+URLНе потрібно вручну двічі кодувати значення, яке вже передається через searchParams. Для цього API саме відповідає за коректне представлення значення в URL.
Нижче функція приймає URL-рядок і номер сторінки, а повертає новий URL. Вихідний рядок не змінюється, оскільки кожен виклик створює новий об’єкт URL.
const { URL } = require('node:url');
function withPage(input, page) {
if (!Number.isInteger(page) || page < 1) {
throw new TypeError('Номер сторінки має бути додатним цілим числом');
}
const address = new URL(input);
address.searchParams.set('page', String(page));
return address.toString();
}
try {
console.log(withPage('https://example.com/products?sort=price', 3));
// https://example.com/products?sort=price&page=3
} catch (error) {
console.error(`Помилка: ${error.message}`);
}Тут виконується кілька важливих дій:
перевіряється значення номера сторінки;
рядок перетворюється на об’єкт URL;
параметр page додається або замінюється через searchParams;
результат перетворюється назад у рядок.
urlМодуль url також містить старий API:
url.parse();
url.format();
url.resolve().
Він досі може траплятися в існуючих проєктах, але для нового коду зазвичай варто використовувати URL і URLSearchParams.
url.parse()const url = require('node:url');
const parsed = url.parse(
'https://example.com/products?page=2',
true
);
console.log(parsed.protocol); // https:
console.log(parsed.hostname); // example.com
console.log(parsed.pathname); // /products
console.log(parsed.query); // { page: '2' }Другий аргумент true перетворює query-рядок на звичайний об’єкт. Без нього query буде рядком:
const url = require('node:url');
const parsed = url.parse('https://example.com/products?page=2');
console.log(parsed.query); // page=2Для нового коду URLSearchParams має чіткішу поведінку, зокрема коректно підтримує параметри з кількома значеннями.
url.format()url.format() будує рядок на основі об’єкта компонентів:
const url = require('node:url');
const result = url.format({
protocol: 'https:',
hostname: 'example.com',
pathname: '/products',
query: {
page: '2',
sort: 'price'
}
});
console.log(result);
// https://example.com/products?page=2&sort=priceСучасний підхід — створити URL і змінювати його властивості:
const { URL } = require('node:url');
const address = new URL('https://example.com/products');
address.searchParams.set('page', '2');
address.searchParams.set('sort', 'price');
console.log(address.href);
// https://example.com/products?page=2&sort=priceurl.resolve()Старий метод url.resolve() використовували для об’єднання базового й відносного URL:
const url = require('node:url');
console.log(
url.resolve('https://example.com/catalog/', 'products')
);
// https://example.com/catalog/productsСучасний еквівалент:
const { URL } = require('node:url');
console.log(
new URL('products', 'https://example.com/catalog/').href
);
// https://example.com/catalog/productsconst { URL } = require('node:url');
const address = new URL('/products');/products — відносний шлях, а не повний URL. Потрібно передати базову адресу:
const address = new URL('/products', 'https://example.com');host і hostnameconst { URL } = require('node:url');
const address = new URL('https://example.com:8443/products');
console.log(address.hostname); // example.com
console.log(address.host); // example.com:8443Якщо порт потрібно врахувати, використовуйте host, а не hostname.
const { URL } = require('node:url');
const address = new URL('https://example.com:8443/products?page=2');
console.log(typeof address.port); // string
console.log(typeof address.searchParams.get('page')); // stringURL зберігає ці значення як рядки. За потреби їх потрібно перетворити явно:
const page = Number(address.searchParams.get('page'));Небажано будувати параметри так:
const value = 'node.js & URL';
const result = 'https://example.com/search?q=' + value;Краще використовувати searchParams:
const { URL } = require('node:url');
const address = new URL('https://example.com/search');
address.searchParams.set('q', 'node.js & URL');
console.log(address.href);Зовнішні дані можуть містити некоректний URL. Створення об’єкта потрібно обробляти:
const { URL } = require('node:url');
function parseUrl(value) {
try {
return new URL(value);
} catch {
return null;
}
}
console.log(parseUrl('https://example.com')?.hostname); // example.com
console.log(parseUrl('invalid')); // nullДля сучасного коду Node.js використовуйте URL з модуля node:url.
URL розділяє адресу на протокол, хост, порт, шлях, query та фрагмент.
Відносні адреси створюються через new URL(relative, base).
Для query-параметрів використовуйте searchParams, а не ручну конкатенацію.
URL можна змінювати через властивості, а потім перетворювати на рядок через href або toString().
url.parse(), url.format() і url.resolve() належать до старого API та переважно потрібні для підтримки наявного коду.
Під час обробки зовнішніх URL враховуйте можливість помилки TypeError.