Парсер URL

Разберите любой URL на протокол, хост, порт, путь, запрос и фрагмент, используя стандарт WHATWG URL. Параметры запроса декодируются в читаемую таблицу.

Разделите URL на каждый компонент, который видит браузер. Вставьте URL, и каждая часть извлекается с использованием того же парсера WHATWG, который использует ваш браузер, поэтому результат точно соответствует тому, как URL будет фактически интерпретирован. Параметры запроса декодируются в таблицу.

Параметры запроса

Анатомия URL

Форма URL

Каждый абсолютный URL следует одному и тому же каркасу:

scheme://user:password@host:port/path?query#fragment

Большинство URL используют лишь горсть этих слотов, но грамматика всегда допускает все их. Чтение URL во многом сводится к тому, чтобы знать, где заканчивается один компонент и начинается следующий, что решается разделителями ://, @, :, /, ? и #.

Компонент за компонентом

Протокол (схема) определяет, как получить ресурс — https:, mailto:, ftp:. Обратите внимание, что парсер WHATWG включает закрывающее двоеточие в это значение, что удивляет тех, кто сравнивает его со строкой "https".

Имя пользователя и пароль — это устаревшая секция userinfo. Браузеры всё ещё разбирают их, но удаляют из запросов и часто предупреждают, потому что встраивание учётных данных в URL раскрывает их в истории, логах и заголовках referrer. Воспринимайте их присутствие в URL, который вы не писали, как фишинговый сигнал.

Имя хоста — это только домен или IP-адрес. Хост — это имя хоста плюс порт, когда присутствует нестандартный порт, поэтому два этих поля здесь часто выглядят одинаково.

Порт пуст, когда URL использует порт по умолчанию для схемы — 443 для https, 80 для http. Парсер нормализует это: example.com:443/ сообщает пустой порт, потому что 443 не добавляет информации.

Путь — это всё от первого / до запроса. Это единственный компонент, который никогда не пуст для URL http(s); голое происхождение получает путь /.

Строка запроса начинается с ? и несёт параметры. Фрагмент начинается с # и является единственной частью, которая никогда не отправляется на сервер — он обрабатывается чисто на стороне клиента, поэтому одностраничные приложения когда-то использовали его для маршрутизации, а токен доступа во фрагменте остаётся вне серверных логов.

Происхождение — это значимая для безопасности тройка схемы, хоста и порта. Два URL имеют общее происхождение только когда совпадают все три, и именно на этом основаны политика одного источника и решения CORS.

Почему парсер строг

Парсер WHATWG URL принимает только абсолютные URL. У example.com/page нет схемы, поэтому он не может быть разобран сам по себе — у парсера нет способа узнать, имели ли вы в виду example.com/page или относительный путь. Реальный код разрешает относительные ссылки относительно базового URL; этот инструмент намеренно требует абсолютной формы, чтобы то, что вы видите, было однозначным.

Нормализация, которую вы заметите

Парсер не возвращает исходную строку. Он приводит схему и хост к нижнему регистру, разрешает сегменты . и .. в пути, отбрасывает порты по умолчанию и преобразует интернационализированные доменные имена в их форму Punycode, поэтому münchen.de сообщает имя хоста xn--mnchen-3ya.de. Это возможность: она показывает URL таким, как сетевой стек действительно будет его трактовать, а не таким, как он был набран.

Повторяющиеся параметры

Строка запроса может законно повторять ключ, как в ?tag=a&tag=b. Никакая спецификация не говорит, что это значит — некоторые фреймворки берут первое значение, некоторые последнее, некоторые собирают массив. Таблица здесь перечисляет каждое вхождение по порядку, чтобы вы видели точно то, что было отправлено, а не свёрнутый вид.

Примечание open source: реализовано с использованием встроенных в браузер API WHATWG URL и URLSearchParams. Сторонние библиотеки не используются.

Часто задаваемые вопросы

Почему поле порта пусто?
Потому что URL использует порт по умолчанию для своей схемы. Парсер WHATWG опускает 443 для https и 80 для http, поскольку их включение не добавляет информации и нарушило бы сравнения происхождения.
Почему протокол включает двоеточие?
Так определяет стандарт URL. Свойство протокола — `https:`, а не `https`. Если вы сравниваете с чистым именем схемы, помните о завершающем двоеточии.
В чём разница между хостом и именем хоста?
Имя хоста — это только домен. Хост включает порт, если он присутствует. Для https://example.com:8443/ именем хоста будет example.com, а хостом — example.com:8443.
Почему я не могу разобрать относительный URL?
Относительная ссылка вроде /about или ../img.png имеет смысл только относительно базового URL. Парсер требует абсолютный URL со схемой, чтобы результат был однозначным.
Отправляется ли фрагмент на сервер?
Нет. Часть после # никогда не передаётся в HTTP-запросе. Она разрешается полностью в браузере, поэтому неявные потоки OAuth использовали её, чтобы держать токены вне серверных логов.
Почему мой домен в Юникоде изменился?
Интернационализированные доменные имена преобразуются в Punycode, ASCII-форму, которую на самом деле использует DNS. münchen.de превращается в xn--mnchen-3ya.de. Это то же преобразование, которое ваш браузер выполняет перед отправкой запроса.