Перейти к содержанию

URL

latest

Стабильность: 2 – Стабильная

АПИ является удовлетворительным. Совместимость с NPM имеет высший приоритет и не будет нарушена кроме случаев явной необходимости.

Модуль node:url предоставляет средства для разрешения и разбора URL. Подключение:

1
import url from 'node:url';
1
const url = require('node:url');

Строки URL и объекты URL

Строка URL — структурированная строка с несколькими смысловыми компонентами. После разбора возвращается объект URL со свойствами для каждого компонента.

В node:url два API: унаследованный, специфичный для Node.js, и новый, соответствующий WHATWG URL Standard, как в браузерах.

Ниже сравнение WHATWG и унаследованного API. Для URL 'https://user:[email protected]:8080/p/a/t/h?query=string#hash' сверху — свойства объекта от унаследованного url.parse(), снизу — свойства WHATWG URL.

У WHATWG origin включает protocol и host, но не username и password.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                              href                                              │
├──────────┬──┬─────────────────────┬────────────────────────┬───────────────────────────┬───────┤
│ protocol │  │        auth         │          host          │           path            │ hash  │
│          │  │                     ├─────────────────┬──────┼──────────┬────────────────┤       │
│          │  │                     │    hostname     │ port │ pathname │     search     │       │
│          │  │                     │                 │      │          ├─┬──────────────┤       │
│          │  │                     │                 │      │          │ │    query     │       │
"  https:   //    user   :   pass   @ sub.example.com : 8080   /p/a/t/h  ?  query=string   #hash "
│          │  │          │          │    hostname     │ port │          │                │       │
│          │  │          │          ├─────────────────┴──────┤          │                │       │
│ protocol │  │ username │ password │          host          │          │                │       │
├──────────┴──┼──────────┴──────────┼────────────────────────┤          │                │       │
│   origin    │                     │         origin         │ pathname │     search     │ hash  │
├─────────────┴─────────────────────┴────────────────────────┴──────────┴────────────────┴───────┤
│                                              href                                              │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
(Все пробелы в строке "" следует игнорировать. Они нужны только для форматирования.)

Разбор строки URL через WHATWG API:

1
2
const myURL =
  new URL('https://user:[email protected]:8080/p/a/t/h?query=string#hash');

Разбор через унаследованный API:

1
2
3
import url from 'node:url';
const myURL =
  url.parse('https://user:[email protected]:8080/p/a/t/h?query=string#hash');
1
2
3
const url = require('node:url');
const myURL =
  url.parse('https://user:[email protected]:8080/p/a/t/h?query=string#hash');

Сборка URL из частей и получение строки

WHATWG URL можно собрать из частей через сеттеры свойств или шаблонную строку:

1
2
3
4
const myURL = new URL('https://example.org');
myURL.pathname = '/a/b/c';
myURL.search = '?d=e';
myURL.hash = '#fgh';
1
2
3
4
const pathname = '/a/b/c';
const search = '?d=e';
const hash = '#fgh';
const myURL = new URL(`https://example.org${pathname}${search}${hash}`);

Итоговую строку URL даёт свойство href:

1
console.log(myURL.href);

WHATWG API для URL

Класс: URL

Совместимый с браузерами класс URL, реализованный по WHATWG URL Standard. Примеры разобранных URL приведены в самом стандарте. Класс URL также доступен в глобальном объекте.

По соглашениям браузеров все свойства объектов URL реализованы как геттеры и сеттеры на прототипе класса, а не как свойства данных самого объекта. Поэтому, в отличие от legacy urlObject, использование ключевого слова delete для любых свойств объектов URL (например, delete myURL.protocol, delete myURL.pathname и т.д.) не даёт эффекта, но всё равно возвращает true.

new URL(input[, base])

  • input <string> Абсолютный или относительный входной URL для разбора. Если input относительный, нужен base. Если input абсолютный, base игнорируется. Если input не строка, сначала выполняется преобразование в строку.
  • base <string> Базовый URL для разрешения, если input не абсолютный. Если base не строка, сначала выполняется преобразование в строку.

Создаёт новый объект URL, разбирая input относительно base. Если base передан строкой, он разбирается так же, как new URL(base).

1
2
const myURL = new URL('/foo', 'https://example.org/');
// https://example.org/foo

Конструктор URL доступен как свойство глобального объекта. Его также можно импортировать из встроенного модуля url:

1
2
import { URL } from 'node:url';
console.log(URL === globalThis.URL); // Prints 'true'.
1
console.log(URL === require('node:url').URL); // Prints 'true'.

TypeError будет выброшен, если input или base не являются допустимыми URL. Значения при необходимости приводятся к строкам. Например:

1
2
const myURL = new URL({ toString: () => 'https://example.org/' });
// https://example.org/

Символы Юникода в имени хоста input автоматически преобразуются в ASCII алгоритмом Punycode.

1
2
const myURL = new URL('https://測試');
// https://xn--g6w251d/

Если заранее неизвестно, абсолютный ли input, а base задан, имеет смысл проверить, что origin объекта URL совпадает с ожидаемым.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let myURL = new URL('http://Example.com/', 'https://example.org/');
// http://example.com/

myURL = new URL('https://Example.com/', 'https://example.org/');
// https://example.com/

myURL = new URL('foo://Example.com/', 'https://example.org/');
// foo://Example.com/

myURL = new URL('http:Example.com/', 'https://example.org/');
// http://example.com/

myURL = new URL('https:Example.com/', 'https://example.org/');
// https://example.org/Example.com/

myURL = new URL('foo:Example.com/', 'https://example.org/');
// foo:Example.com/

url.hash

Читает и задаёт фрагмент URL.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org/foo#bar');
console.log(myURL.hash);
// Prints #bar

myURL.hash = 'baz';
console.log(myURL.href);
// Prints https://example.org/foo#baz

Недопустимые символы URL в значении, присвоенном свойству hash, подвергаются процентному кодированию. Набор кодируемых символов может слегка отличаться от того, что дают url.parse() и url.format().

url.host

Читает и задаёт часть хоста URL.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org:81/foo');
console.log(myURL.host);
// Prints example.org:81

myURL.host = 'example.com:82';
console.log(myURL.href);
// Prints https://example.com:82/foo

Недопустимые значения хоста, присвоенные свойству host, игнорируются.

url.hostname

Читает и задаёт имя хоста в URL. Главное отличие url.host и url.hostname: в url.hostname не входит порт.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const myURL = new URL('https://example.org:81/foo');
console.log(myURL.hostname);
// Prints example.org

// Setting the hostname does not change the port
myURL.hostname = 'example.com';
console.log(myURL.href);
// Prints https://example.com:81/foo

// Use myURL.host to change the hostname and port
myURL.host = 'example.org:82';
console.log(myURL.href);
// Prints https://example.org:82/foo

Недопустимые значения имени хоста, присвоенные свойству hostname, игнорируются.

url.href

Читает и задаёт сериализованный URL.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org/foo');
console.log(myURL.href);
// Prints https://example.org/foo

myURL.href = 'https://example.com/bar';
console.log(myURL.href);
// Prints https://example.com/bar

Чтение свойства href эквивалентно вызову url.toString().

Присвоение нового значения эквивалентно созданию объекта URL через new URL(value); изменяются все свойства объекта.

Если присвоенное значение не является допустимым URL, выбрасывается TypeError.

url.origin

Возвращает только для чтения сериализацию происхождения (origin) URL.

1
2
3
const myURL = new URL('https://example.org/foo/bar?baz');
console.log(myURL.origin);
// Prints https://example.org
1
2
3
4
5
6
const idnURL = new URL('https://測試');
console.log(idnURL.origin);
// Prints https://xn--g6w251d

console.log(idnURL.hostname);
// Prints xn--g6w251d

url.password

Читает и задаёт часть пароля URL.

1
2
3
4
5
6
7
const myURL = new URL('https://abc:[email protected]');
console.log(myURL.password);
// Prints xyz

myURL.password = '123';
console.log(myURL.href);
// Prints https://abc:[email protected]/

Недопустимые символы URL в значении свойства password кодируются процентным кодированием. Набор кодируемых символов может слегка отличаться от url.parse() и url.format().

url.pathname

Читает и задаёт путь URL.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org/abc/xyz?123');
console.log(myURL.pathname);
// Prints /abc/xyz

myURL.pathname = '/abcdef';
console.log(myURL.href);
// Prints https://example.org/abcdef?123

Недопустимые символы URL в значении свойства pathname кодируются процентным кодированием. Набор кодируемых символов может слегка отличаться от url.parse() и url.format().

url.port

Читает и задаёт порт в URL.

Значение порта может быть числом или строкой с числом в диапазоне 065535 (включительно). Если задать порт по умолчанию для текущего protocol объекта URL, свойство port станет пустой строкой ('').

Порт может быть пустой строкой; тогда фактический порт определяется схемой:

протокол порт
"ftp" 21
"file"
"http" 80
"https" 443
"ws" 80
"wss" 443

При присвоении значения порту оно сначала приводится к строке через .toString().

Если строка недопустима, но начинается с цифр, в port попадает ведущее число. Если число вне указанного диапазона, оно игнорируется.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const myURL = new URL('https://example.org:8888');
console.log(myURL.port);
// Prints 8888

// Default ports are automatically transformed to the empty string
// (HTTPS protocol's default port is 443)
myURL.port = '443';
console.log(myURL.port);
// Prints the empty string
console.log(myURL.href);
// Prints https://example.org/

myURL.port = 1234;
console.log(myURL.port);
// Prints 1234
console.log(myURL.href);
// Prints https://example.org:1234/

// Completely invalid port strings are ignored
myURL.port = 'abcd';
console.log(myURL.port);
// Prints 1234

// Leading numbers are treated as a port number
myURL.port = '5678abcd';
console.log(myURL.port);
// Prints 5678

// Non-integers are truncated
myURL.port = 1234.5678;
console.log(myURL.port);
// Prints 1234

// Out-of-range numbers which are not represented in scientific notation
// will be ignored.
myURL.port = 1e10; // 10000000000, will be range-checked as described below
console.log(myURL.port);
// Prints 1234

Числа с десятичной точкой (в том числе с плавающей запятой и в экспоненциальной записи) не исключение: в порт попадает ведущее число до точки, если оно допустимо:

1
2
3
myURL.port = 4.567e21;
console.log(myURL.port);
// Prints 4 (because it is the leading number in the string '4.567e21')

url.protocol

Читает и задаёт схему (протокол) URL.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org');
console.log(myURL.protocol);
// Prints https:

myURL.protocol = 'ftp';
console.log(myURL.href);
// Prints ftp://example.org/

Недопустимые значения протокола, присвоенные свойству protocol, игнорируются.

Особые схемы

WHATWG URL Standard считает ряд схем URL особенными с точки зрения разбора и сериализации. Если URL разобран с особой схемой, свойство url.protocol можно сменить на другую особую схему, но нельзя — на неособую и наоборот.

Например, смена с http на https допустима:

1
2
3
4
const u = new URL('http://example.org');
u.protocol = 'https';
console.log(u.href);
// https://example.org/

Смена с http на гипотетическую схему fish не срабатывает: новая схема не особая.

1
2
3
4
const u = new URL('http://example.org');
u.protocol = 'fish';
console.log(u.href);
// http://example.org/

Аналогично, переход с неособой схемы на особую запрещён:

1
2
3
4
const u = new URL('fish://example.org');
u.protocol = 'http';
console.log(u.href);
// fish://example.org

По WHATWG URL Standard особыми схемами являются ftp, file, http, https, ws и wss.

url.search

Читает и задаёт сериализованную строку запроса URL.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org/abc?123');
console.log(myURL.search);
// Prints ?123

myURL.search = 'abc=xyz';
console.log(myURL.href);
// Prints https://example.org/abc?abc=xyz

Недопустимые символы URL в значении свойства search кодируются процентным кодированием. Набор кодируемых символов может слегка отличаться от url.parse() и url.format().

url.searchParams

Возвращает объект URLSearchParams с параметрами запроса URL. Свойство только для чтения, но через URLSearchParams можно менять экземпляр URL; чтобы полностью заменить строку запроса, используйте сеттер url.search. Подробнее см. URLSearchParams.

При изменении URL через .searchParams учитывайте: по спецификации WHATWG у URLSearchParams другие правила процентного кодирования. Например, объект URL не кодирует тильду ASCII (~), а URLSearchParams кодирует её всегда:

1
2
3
4
5
6
7
8
const myURL = new URL('https://example.org/abc?foo=~bar');

console.log(myURL.search);  // prints ?foo=~bar

// Modify the URL via searchParams...
myURL.searchParams.sort();

console.log(myURL.search);  // prints ?foo=%7Ebar

url.username

Читает и задаёт имя пользователя в URL.

1
2
3
4
5
6
7
const myURL = new URL('https://abc:[email protected]');
console.log(myURL.username);
// Prints abc

myURL.username = '123';
console.log(myURL.href);
// Prints https://123:[email protected]/

Недопустимые символы URL в значении свойства username кодируются процентным кодированием. Набор кодируемых символов может слегка отличаться от url.parse() и url.format().

url.toString()

Метод toString() объекта URL возвращает сериализованный URL; результат совпадает с url.href и url.toJSON().

url.toJSON()

Метод toJSON() объекта URL возвращает сериализованный URL; результат совпадает с url.href и url.toString().

Метод вызывается автоматически при сериализации объекта URL через JSON.stringify().

1
2
3
4
5
6
const myURLs = [
  new URL('https://www.example.com'),
  new URL('https://test.example.org'),
];
console.log(JSON.stringify(myURLs));
// Prints ["https://www.example.com/","https://test.example.org/"]

URL.createObjectURL(blob)

Добавлено в: v16.7.0

Создаёт строку URL 'blob:nodedata:...', представляющую переданный объект Blob; по ней позже можно получить тот же Blob.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const {
  Blob,
  resolveObjectURL,
} = require('node:buffer');

const blob = new Blob(['hello']);
const id = URL.createObjectURL(blob);

// later...

const otherBlob = resolveObjectURL(id);
console.log(otherBlob.size);

Данные зарегистрированного Blob остаются в памяти, пока не будет вызван URL.revokeObjectURL() для их удаления.

Объекты Blob регистрируются в текущем потоке. При использовании Worker Threads Blob, зарегистрированный в одном воркере, недоступен другим воркерам и главному потоку.

URL.revokeObjectURL(id)

Добавлено в: v16.7.0

  • id <string> Строка URL 'blob:nodedata:..., возвращённая предыдущим вызовом URL.createObjectURL().

Удаляет сохранённый Blob с указанным идентификатором. Отзыв незарегистрированного id завершается без ошибки.

URL.canParse(input[, base])

Проверяет, можно ли разобрать input относительно base в корректный URL.

1
2
3
const isValid = URL.canParse('/foo', 'https://example.org/'); // true

const isNotValid = URL.canParse('/foo'); // false

URL.parse(input[, base])

Разбирает строку как URL. Если задан base, он используется для разрешения неабсолютных input. Возвращает null, если параметры нельзя привести к допустимому URL.

Класс: URLPattern

Стабильность: 1 - Экспериментальная

API URLPattern сопоставляет URL или их части с шаблоном.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
const myPattern = new URLPattern('https://nodejs.org/docs/latest/api/*.html');
console.log(myPattern.exec('https://nodejs.org/docs/latest/api/dns.html'));
// Prints:
// {
//  "hash": { "groups": {  "0": "" },  "input": "" },
//  "hostname": { "groups": {}, "input": "nodejs.org" },
//  "inputs": [
//    "https://nodejs.org/docs/latest/api/dns.html"
//  ],
//  "password": { "groups": { "0": "" }, "input": "" },
//  "pathname": { "groups": { "0": "dns" }, "input": "/docs/latest/api/dns.html" },
//  "port": { "groups": {}, "input": "" },
//  "protocol": { "groups": {}, "input": "https" },
//  "search": { "groups": { "0": "" }, "input": "" },
//  "username": { "groups": { "0": "" }, "input": "" }
// }

console.log(myPattern.test('https://nodejs.org/docs/latest/api/dns.html'));
// Prints: true

new URLPattern()

Создаёт пустой объект URLPattern.

new URLPattern(string[, baseURL][, options])

Разбирает string как URL и создаёт по нему новый URLPattern.

Если baseURL не указан, по умолчанию undefined.

В options может быть булево ignoreCase для сопоставления без учёта регистра.

Конструктор может выбросить TypeError при ошибке разбора.

new URLPattern(obj[, baseURL][, options])

  • obj <Object> Объект шаблона
  • baseURL <string> | undefined Базовый URL
  • options <Object> Параметры

Разбирает Object как шаблон и создаёт URLPattern. Поля: protocol, username, password, hostname, port, pathname, search, hash или baseURL.

Если baseURL не указан, по умолчанию undefined.

В options может быть булево ignoreCase для сопоставления без учёта регистра.

Конструктор может выбросить TypeError при ошибке разбора.

urlPattern.exec(input[, baseURL])

input — строка или объект с частями URL: protocol, username, password, hostname, port, pathname, search, hash или baseURL.

Если baseURL не указан, по умолчанию undefined.

Возвращает объект с ключом inputs (массив аргументов вызова) и ключами компонентов URL с совпавшими input и группами.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const myPattern = new URLPattern('https://nodejs.org/docs/latest/api/*.html');
console.log(myPattern.exec('https://nodejs.org/docs/latest/api/dns.html'));
// Prints:
// {
//  "hash": { "groups": {  "0": "" },  "input": "" },
//  "hostname": { "groups": {}, "input": "nodejs.org" },
//  "inputs": [
//    "https://nodejs.org/docs/latest/api/dns.html"
//  ],
//  "password": { "groups": { "0": "" }, "input": "" },
//  "pathname": { "groups": { "0": "dns" }, "input": "/docs/latest/api/dns.html" },
//  "port": { "groups": {}, "input": "" },
//  "protocol": { "groups": {}, "input": "https" },
//  "search": { "groups": { "0": "" }, "input": "" },
//  "username": { "groups": { "0": "" }, "input": "" }
// }

urlPattern.test(input[, baseURL])

Семантика input и baseURL такая же, как у urlPattern.exec.

Возвращает true, если input соответствует шаблону.

1
2
3
const myPattern = new URLPattern('https://nodejs.org/docs/latest/api/*.html');
console.log(myPattern.test('https://nodejs.org/docs/latest/api/dns.html'));
// Prints: true

Класс: URLSearchParams

API URLSearchParams даёт доступ на чтение и запись к строке запроса URL. Класс можно использовать отдельно — ниже четыре варианта конструктора. Класс также доступен в глобальном объекте.

Интерфейс WHATWG URLSearchParams и модуль querystring решают похожую задачу, но querystring универсальнее: можно настраивать разделители (& и =). Этот API предназначен именно для строк запроса в URL.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const myURL = new URL('https://example.org/?abc=123');
console.log(myURL.searchParams.get('abc'));
// Prints 123

myURL.searchParams.append('abc', 'xyz');
console.log(myURL.href);
// Prints https://example.org/?abc=123&abc=xyz

myURL.searchParams.delete('abc');
myURL.searchParams.set('a', 'b');
console.log(myURL.href);
// Prints https://example.org/?a=b

const newSearchParams = new URLSearchParams(myURL.searchParams);
// The above is equivalent to
// const newSearchParams = new URLSearchParams(myURL.search);

newSearchParams.append('a', 'c');
console.log(myURL.href);
// Prints https://example.org/?a=b
console.log(newSearchParams.toString());
// Prints a=b&a=c

// newSearchParams.toString() is implicitly called
myURL.search = newSearchParams;
console.log(myURL.href);
// Prints https://example.org/?a=b&a=c
newSearchParams.delete('a');
console.log(myURL.href);
// Prints https://example.org/?a=b&a=c

new URLSearchParams()

Создаёт пустой URLSearchParams.

new URLSearchParams(string)

  • string <string> Строка запроса

Разбирает string как строку запроса и создаёт URLSearchParams. Ведущий '?, если есть, игнорируется.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let params;

params = new URLSearchParams('user=abc&query=xyz');
console.log(params.get('user'));
// Prints 'abc'
console.log(params.toString());
// Prints 'user=abc&query=xyz'

params = new URLSearchParams('?user=abc&query=xyz');
console.log(params.toString());
// Prints 'user=abc&query=xyz'

new URLSearchParams(obj)

  • obj <Object> Объект с парами ключ–значение

Создаёт URLSearchParams из обычного объекта. Ключи и значения свойств obj приводятся к строкам.

В отличие от querystring, дубликаты ключей в виде массивов не поддерживаются: массивы приводятся через array.toString() — элементы склеиваются запятыми.

1
2
3
4
5
6
7
8
const params = new URLSearchParams({
  user: 'abc',
  query: ['first', 'second'],
});
console.log(params.getAll('query'));
// Prints [ 'first,second' ]
console.log(params.toString());
// Prints 'user=abc&query=first%2Csecond'

new URLSearchParams(iterable)

  • iterable <Iterable> Итерируемый объект с парами ключ–значение

Создаёт URLSearchParams из итерируемой карты по аналогии с конструктором Map. iterable может быть Array или любым итерируемым объектом, в том числе другим URLSearchParams — тогда получится клон. Элементы — пары ключ–значение; каждая пара может быть любым итерируемым объектом.

Дубликаты ключей допускаются.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
let params;

// Using an array
params = new URLSearchParams([
  ['user', 'abc'],
  ['query', 'first'],
  ['query', 'second'],
]);
console.log(params.toString());
// Prints 'user=abc&query=first&query=second'

// Using a Map object
const map = new Map();
map.set('user', 'abc');
map.set('query', 'xyz');
params = new URLSearchParams(map);
console.log(params.toString());
// Prints 'user=abc&query=xyz'

// Using a generator function
function* getQueryPairs() {
  yield ['user', 'abc'];
  yield ['query', 'first'];
  yield ['query', 'second'];
}
params = new URLSearchParams(getQueryPairs());
console.log(params.toString());
// Prints 'user=abc&query=first&query=second'

// Each key-value pair must have exactly two elements
new URLSearchParams([
  ['user', 'abc', 'error'],
]);
// Throws TypeError [ERR_INVALID_TUPLE]:
//        Each query pair must be an iterable [name, value] tuple

urlSearchParams.append(name, value)

Добавляет пару имя–значение в строку запроса.

urlSearchParams.delete(name[, value])

Если передан value, удаляются все пары с данным name и value.

Если value не передан, удаляются все пары с именем name.

urlSearchParams.entries()

Возвращает ES6-итератор по парам имя–значение в запросе. Каждый элемент — массив Array: первый элемент — name, второй — value.

Синоним [urlSearchParams[Symbol.iterator]()][urlSearchParamsSymbol.iterator()].

urlSearchParams.forEach(fn[, thisArg])

  • fn <Function> Вызывается для каждой пары имя–значение
  • thisArg <Object> Значение this при вызове fn

Обходит пары имя–значение и вызывает fn для каждой.

1
2
3
4
5
6
7
const myURL = new URL('https://example.org/?a=b&c=d');
myURL.searchParams.forEach((value, name, searchParams) => {
  console.log(name, value, myURL.searchParams === searchParams);
});
// Prints:
//   a b true
//   c d true

urlSearchParams.get(name)

  • name <string>
  • Возвращает: <string> | null Строка или null, если пары с таким name нет.

Возвращает значение первой пары с именем name; если таких пар нет — null.

urlSearchParams.getAll(name)

Возвращает значения всех пар с именем name; если таких пар нет — пустой массив.

urlSearchParams.has(name[, value])

Проверяет наличие пар по name и необязательному value.

Если value задан, возвращает true, если есть пара с тем же name и value.

Если value не задан, возвращает true, если есть хотя бы одна пара с именем name.

urlSearchParams.keys()

Возвращает ES6-итератор по именам в парах имя–значение.

1
2
3
4
5
6
7
const params = new URLSearchParams('foo=bar&foo=baz');
for (const name of params.keys()) {
  console.log(name);
}
// Prints:
//   foo
//   foo

urlSearchParams.set(name, value)

Задаёт для name значение value. Если уже есть пары с именем name, у первой пары меняется значение на value, остальные с тем же именем удаляются; иначе добавляется новая пара.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const params = new URLSearchParams();
params.append('foo', 'bar');
params.append('foo', 'baz');
params.append('abc', 'def');
console.log(params.toString());
// Prints foo=bar&foo=baz&abc=def

params.set('foo', 'def');
params.set('xyz', 'opq');
console.log(params.toString());
// Prints foo=def&abc=def&xyz=opq

urlSearchParams.size

Общее число записей параметров.

urlSearchParams.sort()

Сортирует пары имя–значение на месте по имени. Используется устойчивый алгоритм сортировки, порядок пар с одинаковым именем сохраняется.

Метод полезен, в частности, для повышения попаданий в кэш.

1
2
3
4
const params = new URLSearchParams('query[]=abc&type=search&query[]=123');
params.sort();
console.log(params.toString());
// Prints query%5B%5D=abc&query%5B%5D=123&type=search

urlSearchParams.toString()

Возвращает параметры запроса в виде строки с необходимым процентным кодированием.

urlSearchParams.values()

Возвращает ES6-итератор по значениям в парах имя–значение.

urlSearchParams[Symbol.iterator]()

Возвращает ES6-итератор по парам имя–значение в строке запроса. Каждый элемент — массив Array: первый элемент — name, второй — value.

Синоним urlSearchParams.entries().

1
2
3
4
5
6
7
const params = new URLSearchParams('foo=bar&xyz=baz');
for (const [name, value] of params) {
  console.log(name, value);
}
// Prints:
//   foo bar
//   xyz baz

url.domainToASCII(domain)

Возвращает ASCII-представление domain в Punycode. Если домен недопустим — пустая строка.

Обратная операция к url.domainToUnicode().

1
2
3
4
5
6
7
8
import url from 'node:url';

console.log(url.domainToASCII('español.com'));
// Prints xn--espaol-zwa.com
console.log(url.domainToASCII('中文.com'));
// Prints xn--fiq228c.com
console.log(url.domainToASCII('xn--iñvalid.com'));
// Prints an empty string
1
2
3
4
5
6
7
8
const url = require('node:url');

console.log(url.domainToASCII('español.com'));
// Prints xn--espaol-zwa.com
console.log(url.domainToASCII('中文.com'));
// Prints xn--fiq228c.com
console.log(url.domainToASCII('xn--iñvalid.com'));
// Prints an empty string

url.domainToUnicode(domain)

Возвращает Unicode-представление domain. Если домен недопустим — пустая строка.

Обратная операция к url.domainToASCII().

1
2
3
4
5
6
7
8
import url from 'node:url';

console.log(url.domainToUnicode('xn--espaol-zwa.com'));
// Prints español.com
console.log(url.domainToUnicode('xn--fiq228c.com'));
// Prints 中文.com
console.log(url.domainToUnicode('xn--iñvalid.com'));
// Prints an empty string
1
2
3
4
5
6
7
8
const url = require('node:url');

console.log(url.domainToUnicode('xn--espaol-zwa.com'));
// Prints español.com
console.log(url.domainToUnicode('xn--fiq228c.com'));
// Prints 中文.com
console.log(url.domainToUnicode('xn--iñvalid.com'));
// Prints an empty string

url.fileURLToPath(url[, options])

Добавлено в: v10.12.0

  • url <URL> | <string> Строка file URL или объект URL для преобразования в путь.
  • options <Object>
  • windows <boolean> | undefined true — путь как в Windows, false — POSIX, undefined — по умолчанию для системы. По умолчанию: undefined.
  • Возвращает: <string> Полностью разрешённый путь к файлу для текущей платформы.

Функция корректно декодирует процентное кодирование и возвращает допустимую абсолютную строку пути на разных платформах.

Безопасность:

Декодируются процентно закодированные символы, в том числе сегменты с точками (%2e., %2e%2e..), затем путь нормализуется. Закодированные обходы каталога (например %2e%2e) превращаются в реальный обход, при этом закодированные слэши (%2F, %5C) по-прежнему отклоняются.

Нельзя полагаться только на fileURLToPath() против атак с обходом каталога. Всегда явно проверяйте полученный путь и границы допустимых каталогов перед операциями с файловой системой.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);

new URL('file:///C:/path/').pathname;      // Incorrect: /C:/path/
fileURLToPath('file:///C:/path/');         // Correct:   C:\path\ (Windows)

new URL('file://nas/foo.txt').pathname;    // Incorrect: /foo.txt
fileURLToPath('file://nas/foo.txt');       // Correct:   \\nas\foo.txt (Windows)

new URL('file:///你好.txt').pathname;      // Incorrect: /%E4%BD%A0%E5%A5%BD.txt
fileURLToPath('file:///你好.txt');         // Correct:   /你好.txt (POSIX)

new URL('file:///hello world').pathname;   // Incorrect: /hello%20world
fileURLToPath('file:///hello world');      // Correct:   /hello world (POSIX)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const { fileURLToPath } = require('node:url');
new URL('file:///C:/path/').pathname;      // Incorrect: /C:/path/
fileURLToPath('file:///C:/path/');         // Correct:   C:\path\ (Windows)

new URL('file://nas/foo.txt').pathname;    // Incorrect: /foo.txt
fileURLToPath('file://nas/foo.txt');       // Correct:   \\nas\foo.txt (Windows)

new URL('file:///你好.txt').pathname;      // Incorrect: /%E4%BD%A0%E5%A5%BD.txt
fileURLToPath('file:///你好.txt');         // Correct:   /你好.txt (POSIX)

new URL('file:///hello world').pathname;   // Incorrect: /hello%20world
fileURLToPath('file:///hello world');      // Correct:   /hello world (POSIX)

url.fileURLToPathBuffer(url[, options])

  • url <URL> | <string> Строка file URL или объект URL для преобразования в путь.
  • options <Object>
  • windows <boolean> | undefined true — путь как в Windows, false — POSIX, undefined — по умолчанию для системы. По умолчанию: undefined.
  • Возвращает: <Buffer> Полностью разрешённый путь к файлу в виде Buffer.

Как url.fileURLToPath(...), но возвращается Buffer вместо строки. Удобно, если в URL есть процентно закодированные фрагменты, не являющиеся корректным UTF-8.

Безопасность:

Те же риски, что у url.fileURLToPath(): декодирование и нормализация пути. Нельзя полагаться только на эту функцию против атак с обходом каталога. Проверяйте полученный Buffer перед использованием в ФС.

url.format(URL[, options])

  • URL <URL> Объект WHATWG URL
  • options <Object>
  • auth <boolean> true — включать имя пользователя и пароль в строку, иначе нет. По умолчанию: true.
  • fragment <boolean> true — включать фрагмент. По умолчанию: true.
  • search <boolean> true — включать строку запроса. По умолчанию: true.
  • unicode <boolean> true — символы Юникода в хосте кодируются напрямую, а не через Punycode. По умолчанию: false.
  • Возвращает: <string>

Настраиваемая сериализация объекта WHATWG URL в строку.

У объекта URL есть toString() и href, но без настроек. url.format(URL[, options]) даёт базовую настройку вывода.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import url from 'node:url';
const myURL = new URL('https://a:b@測試?abc#foo');

console.log(myURL.href);
// Prints https://a:b@xn--g6w251d/?abc#foo

console.log(myURL.toString());
// Prints https://a:b@xn--g6w251d/?abc#foo

console.log(url.format(myURL, { fragment: false, unicode: true, auth: false }));
// Prints 'https://測試/?abc'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const url = require('node:url');
const myURL = new URL('https://a:b@測試?abc#foo');

console.log(myURL.href);
// Prints https://a:b@xn--g6w251d/?abc#foo

console.log(myURL.toString());
// Prints https://a:b@xn--g6w251d/?abc#foo

console.log(url.format(myURL, { fragment: false, unicode: true, auth: false }));
// Prints 'https://測試/?abc'

url.pathToFileURL(path[, options])

Добавлено в: v10.12.0

  • path <string> Путь для преобразования в file URL.
  • options <Object>
  • windows <boolean> | undefined true — путь как в Windows, false — POSIX, undefined — по умолчанию для системы. По умолчанию: undefined.
  • Возвращает: <URL> Объект file URL.

Функция разрешает path в абсолютный путь и корректно кодирует управляющие символы при преобразовании в file URL.

1
2
3
4
5
6
7
import { pathToFileURL } from 'node:url';

new URL('/foo#1', 'file:');           // Incorrect: file:///foo#1
pathToFileURL('/foo#1');              // Correct:   file:///foo%231 (POSIX)

new URL('/some/path%.c', 'file:');    // Incorrect: file:///some/path%.c
pathToFileURL('/some/path%.c');       // Correct:   file:///some/path%25.c (POSIX)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const { pathToFileURL } = require('node:url');
new URL(__filename);                  // Incorrect: throws (POSIX)
new URL(__filename);                  // Incorrect: C:\... (Windows)
pathToFileURL(__filename);            // Correct:   file:///... (POSIX)
pathToFileURL(__filename);            // Correct:   file:///C:/... (Windows)

new URL('/foo#1', 'file:');           // Incorrect: file:///foo#1
pathToFileURL('/foo#1');              // Correct:   file:///foo%231 (POSIX)

new URL('/some/path%.c', 'file:');    // Incorrect: file:///some/path%.c
pathToFileURL('/some/path%.c');       // Correct:   file:///some/path%25.c (POSIX)

url.urlToHttpOptions(url)

  • url <URL> Объект WHATWG URL для преобразования в объект опций.
  • Возвращает: <Object> Объект опций
  • protocol <string> Протокол.
  • hostname <string> Доменное имя или IP сервера.
  • hash <string> Фрагмент URL.
  • search <string> Сериализованная строка запроса.
  • pathname <string> Путь URL.
  • path <string> Путь запроса; при наличии строки запроса она включена. Например '/index.html?page=12'. Исключение при недопустимых символах в пути (сейчас отклоняются пробелы; правила могут измениться).
  • href <string> Сериализованный URL.
  • port <number> Порт удалённого сервера.
  • auth <string> Basic-авторизация в виде 'user:password' для заголовка Authorization.

Преобразует объект URL в обычный объект опций для http.request() и https.request().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import { urlToHttpOptions } from 'node:url';
const myURL = new URL('https://a:b@測試?abc#foo');

console.log(urlToHttpOptions(myURL));
/*
{
  protocol: 'https:',
  hostname: 'xn--g6w251d',
  hash: '#foo',
  search: '?abc',
  pathname: '/',
  path: '/?abc',
  href: 'https://a:b@xn--g6w251d/?abc#foo',
  auth: 'a:b'
}
*/
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const { urlToHttpOptions } = require('node:url');
const myURL = new URL('https://a:b@測試?abc#foo');

console.log(urlToHttpOptions(myURL));
/*
{
  protocol: 'https:',
  hostname: 'xn--g6w251d',
  hash: '#foo',
  search: '?abc',
  pathname: '/',
  path: '/?abc',
  href: 'https://a:b@xn--g6w251d/?abc#foo',
  auth: 'a:b'
}
*/

Унаследованный API URL

Стабильность: 3 - Устаревшее

Предпочитайте WHATWG URL API.

Устаревший urlObject

Унаследованный urlObject (require('node:url').Url или import { Url } from 'node:url') создаётся и возвращается функцией url.parse().

urlObject.auth

Свойство auth — часть URL с именем пользователя и паролем (userinfo). Эта подстрока идёт после protocol и двойного слэша (если есть) и перед компонентом host, отделённая символом @. Строка — либо только имя пользователя, либо имя:пароль.

Например: 'user:pass'.

urlObject.hash

Свойство hash — идентификатор фрагмента URL, включая ведущий #.

Например: '#hash'.

urlObject.host

Свойство host — вся часть хоста в нижнем регистре, включая port, если указан.

Например: 'sub.example.com:8080'.

urlObject.hostname

Свойство hostname — имя хоста в нижнем регистре из компонента host без port.

Например: 'sub.example.com'.

urlObject.href

Свойство href — полная строка URL после разбора; компоненты protocol и host приведены к нижнему регистру.

Например: 'http://user:[email protected]:8080/p/a/t/h?query=string#hash'.

urlObject.path

Свойство path — конкатенация pathname и search.

Например: '/p/a/t/h?query=string'.

Декодирование path не выполняется.

urlObject.pathname

Свойство pathname — весь путь URL: после host (включая port) и до начала query или hash, разделители — ASCII ? или #.

Например: '/p/a/t/h'.

Декодирование строки пути не выполняется.

urlObject.port

Свойство port — числовая часть порта компонента host.

Например: '8080'.

urlObject.protocol

Свойство protocol — схема протокола URL в нижнем регистре.

Например: 'http:'.

urlObject.query

Свойство query — либо строка запроса без ведущего ASCII ?, либо объект из метода parse() модуля querystring. Тип задаётся аргументом parseQueryString в url.parse().

Например: 'query=string' или {'query': 'string'}.

Если это строка, декодирование не выполняется; если объект — декодируются и ключи, и значения.

urlObject.search

Свойство search — вся «строка запроса» URL, включая ведущий ASCII ?.

Например: '?query=string'.

Декодирование строки запроса не выполняется.

urlObject.slashes

Свойство slashesboolean: true, если после двоеточия в protocol нужны два ASCII-слэша (/).

url.format(urlObject)

Добавлено в: v0.1.25

  • urlObject <Object> Объект URL (как из url.parse() или собранный вручную).

Метод url.format() возвращает отформатированную строку URL из urlObject.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const url = require('node:url');
url.format({
  protocol: 'https',
  hostname: 'example.com',
  pathname: '/some/path',
  query: {
    page: 1,
    format: 'json',
  },
});

// => 'https://example.com/some/path?page=1&format=json'

Если urlObject не объект и не строка, url.format() выбросит TypeError.

Форматирование выполняется так:

  • Создаётся пустая строка result.
  • Если urlObject.protocol — строка, она добавляется в result как есть.
  • Иначе, если urlObject.protocol не undefined и не строка, выбрасывается Error.
  • Для строковых значений urlObject.protocol, которые не заканчиваются ASCII-двоеточием (:), к result добавляется литерал :.
  • Если выполняется одно из условий, к result добавляется литерал //:
  • свойство urlObject.slashes истинно;
  • urlObject.protocol начинается с http, https, ftp, gopher или file;
  • Если urlObject.auth истинно и urlObject.host или urlObject.hostname не undefined, значение urlObject.auth приводится к строке, добавляется к result, затем литерал @.
  • Если urlObject.hostundefined:
  • если urlObject.hostname — строка, она добавляется к result;
  • иначе, если urlObject.hostname не undefined и не строка, выбрасывается Error;
  • если urlObject.port истинно и urlObject.hostname не undefined: к result добавляется : и строковое значение urlObject.port.
  • Иначе, если urlObject.host истинно, его значение приводится к строке и добавляется к result.
  • Если urlObject.pathname — непустая строка:
  • если urlObject.pathname не начинается с ASCII /, к result добавляется '/';
  • затем добавляется значение urlObject.pathname.
  • Иначе, если urlObject.pathname не undefined и не строка, выбрасывается Error.
  • Если urlObject.searchundefined, а urlObject.query — объект, к result добавляется ? и результат вызова stringify() модуля querystring для urlObject.query.
  • Иначе, если urlObject.search — строка:
  • если она не начинается с ASCII ?, к result добавляется ?;
  • затем добавляется значение urlObject.search.
  • Иначе, если urlObject.search не undefined и не строка, выбрасывается Error.
  • Если urlObject.hash — строка:
  • если она не начинается с ASCII #, к result добавляется #;
  • затем добавляется значение urlObject.hash.
  • Иначе, если urlObject.hash не undefined и не строка, выбрасывается Error.
  • Возвращается result.

Доступна автоматическая миграция (исходники).

1
npx codemod@latest @nodejs/node-url-to-whatwg-url

url.format(urlString)

Добавлено в: v0.1.25

Стабильность: 0 - Устарело

Предпочитайте WHATWG URL API.

  • urlString <string> Строка, которая будет передана в url.parse(), затем отформатирована.

url.format(urlString) — сокращение для url.format(url.parse(urlString)).

Внутри вызывается устаревший url.parse(), поэтому передача строки в url.format() сама по себе устарела.

Канонизацию строки URL лучше делать через WHATWG URL API: new URL(...) и url.toString().

1
2
3
4
5
6
import { URL } from 'node:url';

const unformatted = 'http://[fe80:0:0:0:0:0:0:1]:/a/b?a=b#abc';
const formatted = new URL(unformatted).toString();

console.log(formatted); // Prints: http://[fe80::1]/a/b?a=b#abc
1
2
3
4
5
6
const { URL } = require('node:url');

const unformatted = 'http://[fe80:0:0:0:0:0:0:1]:/a/b?a=b#abc';
const formatted = new URL(unformatted).toString();

console.log(formatted); // Prints: http://[fe80::1]/a/b?a=b#abc

url.parse(urlString[, parseQueryString[, slashesDenoteHost]])

Добавлено в: v0.1.25

Стабильность: 0 - Устарело

Предпочитайте WHATWG URL API.

  • urlString <string> Строка URL для разбора.
  • parseQueryString <boolean> Если true, свойство query всегда будет объектом из метода parse() модуля querystring. Если false — неразобранная строка. По умолчанию: false.
  • slashesDenoteHost <boolean> Если true, первый фрагмент после литерала // до следующего / считается host. Например, для //foo/bar получится {host: 'foo', pathname: '/bar'}, а не {pathname: '//foo/bar'}. По умолчанию: false.

Метод url.parse() разбирает строку URL и возвращает объект URL.

Если urlString не строка, выбрасывается TypeError.

Если есть auth, но его нельзя декодировать — URIError.

url.parse() использует мягкий нестандартный алгоритм; возможны уязвимости вроде подмены имени хоста и ошибок с учётными данными. Не применяйте к недоверенным данным. Для CVE по url.parse() не выпускаются. Используйте WHATWG URL, например:

1
2
3
4
5
function getURL(req) {
  const proto = req.headers['x-forwarded-proto'] || 'https';
  const host = req.headers['x-forwarded-host'] || req.headers.host || 'example.com';
  return new URL(`${proto}://${host}${req.url || '/'}`);
}

Пример выше предполагает, что от обратного прокси передаются корректные заголовки. Без обратного прокси используйте вариант ниже:

1
2
3
function getURL(req) {
  return new URL(`https://example.com${req.url || '/'}`);
}

Доступна автоматическая миграция (исходники).

1
npx codemod@latest @nodejs/node-url-to-whatwg-url

url.resolve(from, to)

Добавлено в: v0.1.25

Стабильность: 0 - Устарело

Предпочитайте WHATWG URL API.

  • from <string> Базовый URL, если to относительный.
  • to <string> Целевой URL для разрешения.

Метод url.resolve() разрешает целевой URL относительно базового примерно так же, как браузер для <a href>.

1
2
3
4
const url = require('node:url');
url.resolve('/one/two/three', 'four');         // '/one/two/four'
url.resolve('http://example.com/', '/one');    // 'http://example.com/one'
url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'

Внутри вызывается устаревший url.parse(), поэтому url.resolve() устарел.

Тот же результат через WHATWG URL API:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function resolve(from, to) {
  const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
  if (resolvedUrl.protocol === 'resolve:') {
    // `from` is a relative URL.
    const { pathname, search, hash } = resolvedUrl;
    return pathname + search + hash;
  }
  return resolvedUrl.toString();
}

resolve('/one/two/three', 'four');         // '/one/two/four'
resolve('http://example.com/', '/one');    // 'http://example.com/one'
resolve('http://example.com/one', '/two'); // 'http://example.com/two'

Процентное кодирование в URL

В URL допустим только определённый набор символов. Всё, что вне него, нужно кодировать. Способ и набор символов зависят от позиции символа в структуре URL.

Унаследованный API

В унаследованном API пробелы (' ') и перечисленные ниже символы в свойствах объектов URL экранируются автоматически:

1
< > " ` \r \n \t { } | \ ^ '

Например, пробел ASCII (' ') кодируется как %20. Прямой слэш ASCII (/) — как %3C.

API WHATWG

WHATWG URL Standard задаёт более выборочный и детальный набор кодируемых символов, чем унаследованный API.

Алгоритм WHATWG определяет четыре «набора процентного кодирования»:

  • C0 control percent-encode set — кодовые точки U+0000–U+001F (включительно) и все выше U+007E (~).

  • fragment percent-encode set — включает C0 control percent-encode set и точки U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), U+0060 (`).

  • path percent-encode set — включает C0 control percent-encode set и точки U+0020 SPACE, U+0022 ("), U+0023 (#), U+003C (<), U+003E (>), U+003F (?), U+0060 (`), U+007B ({), U+007D (}).

  • userinfo encode set — включает path percent-encode set и точки U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+0040 (@), U+005B ([)–U+005E(^), U+007C (|).

Набор userinfo percent-encode set используется для имени пользователя и пароля в URL. path percent-encode set — для пути большинства URL. fragment percent-encode set — для фрагментов. C0 control percent-encode set — для хоста и пути в особых случаях и в прочих ситуациях по правилам стандарта.

Небуквенные символы в имени хоста кодируются через Punycode. Имя хоста может содержать и Punycode, и процентное кодирование:

1
2
3
4
5
const myURL = new URL('https://%CF%80.example.com/foo');
console.log(myURL.href);
// Prints https://xn--1xa.example.com/foo
console.log(myURL.origin);
// Prints https://xn--1xa.example.com

Комментарии