Содержание
  1. Две рамки: общий синтаксис RFC 3986 и web URL по WHATWG
  2. Пять строк учебного набора
  3. Матрица выбора рамки и условия пересмотра
  4. Эталон разбора первой строки по компонентам
  5. Разрешение относительных ссылок от базы
  6. Отрицательный случай 1bad:thing
  7. Fragment и HTTP request target в форме origin-form
  8. План проверки читателя
  9. Частые вопросы
Гайды

URI и URL: разбор адреса и проверка на учебном наборе

6 ноября 2026 · 9 минут чтения

URI и URL: разбор адреса и проверка на учебном наборе строится на пяти строках. RFC 3986 задаёт общий синтаксис идентификатора, WHATWG описывает web URL и его парсер. Ниже — эталон разбора, разрешение относительных ссылок от базы и отрицательный случай.

Две рамки: общий синтаксис RFC 3986 и web URL по WHATWG

RFC 3986 описывает общий синтаксис идентификатора. По грамматике этого документа URI-reference есть либо URI, либо relative-ref; URI начинается со схемы, за которой идёт двоеточие, а имя схемы начинается с буквы. Схема определяет способ идентификации ресурса в своём пространстве имён. Документ RFC 3986 прямо говорит, что URL — это подмножество URI, у которого есть средство locating: описание основного механизма доступа, например сетевого расположения. URN исторически обозначает идентификаторы схемы «urn», обязанные оставаться глобально уникальными и постоянными. При этом отдельная схема не обязана быть только именем или только локатором: экземпляры URI одной схемы могут иметь свойства и того, и другого. Будущим спецификациям RFC 3986 рекомендует использовать общий термин URI.

WHATWG описывает web URL отдельно. В целях стандарта сказано: он выравнивает RFC 3986 и RFC 3987 с современными реализациями и объявляет эти RFC устаревшими в процессе; пробелы, «нелегальные» кодовые точки, кодирование query, равенство и канонизация — понятия, которые не полностью совпадают или не полностью определены. Стандарт фиксирует термин URL и заявляет, что на практике для URI и IRI используется один алгоритм. Парсер URL принимает произвольную строку и возвращает либо URL, либо отказ, попутно записывая ошибки валидации. Этот парсер не доказывает соответствие грамматике RFC и не подаётся как её замена: рамки решают разные задачи и не выводятся одна из другой.

Пять строк учебного набора

Учебный набор задан заранее и берётся без изменений. Пять строк:

ТЕКСТ5 строк
https://example.test/a?x=1#part
urn:isbn:9780131103627
/help?q=2
../img/a.png
1bad:thing

Первая строка — абсолютный адрес с http(s)-схемой, путём, query и fragment. Вторая — идентификатор схемы urn с номером ISBN. Третья начинается с одного слэша: это ссылка с абсолютным путём, привязанная к базе. Четвёртая начинается с двух точек: относительный путь, который поднимается на уровень выше базы. Пятая начинается с цифры и содержит двоеточие в первом сегменте — это отрицательный случай.

Набор держит три разных типа входа: абсолютные адреса, относительные ссылки и строку, которая не проходит грамматику. Такой состав позволяет проверить не только разбор, но и отказ. Строки короткие, их удобно вставлять в чек-лист и сверять результат построчно. Дальше разбираем каждую по компонентам и по правилам.

Матрица выбора рамки и условия пересмотра

Выбор инструмента зависит от задачи. Матрица ниже фиксирует условия и оставляет неизвестное явно отмеченным.

Задача Рамка Что даёт Ограничение
Строгая проверка общего синтаксиса RFC 3986 Грамматика URI-reference, URI, relative-ref, absolute-URI Не описывает поведение web-парсера
Поведение web-парсера WHATWG Приём произвольной строки, URL или отказ, ошибки валидации Не доказывает соответствие грамматике RFC
Разбор компонентов для http(s) Выбранный пример Восстановление scheme, host, path, query, fragment Покрывает только разобранный класс адресов
Поведение конкретных реализаций за пределами этих рамок — Неизвестно Требует отдельной проверки

Рекомендация условна. Если нужна строгая проверка общего синтаксиса — берётся рамка RFC 3986. Если нужно поведение web-парсера — берётся рамка WHATWG. Если нужен только разбор компонентов для http(s) — достаточно выбранного примера. Неизвестным остаётся поведение конкретных реализаций за пределами этих рамок.

Условия пересмотра: смена требований к строгости и смена среды разбора. Когда проверка переходит из учебного разбора в конвейер, где строки приходят от пользователя, приоритет меняется на поведение парсера. Когда строка идёт в протокол с жёсткой грамматикой, приоритет у RFC. При каждом таком переходе матрицу пересматривают заново.

Эталон разбора первой строки по компонентам

Первая строка — https://example.test/a?x=1#part. По RFC 3986 это URI с допустимой схемой и fragment. Отдельный production absolute-URI из §4.3 fragment не допускает, поэтому первая строка ему не соответствует, оставаясь при этом URI. Это различие важно: absolute-URI — более узкое правило, применяемое там, где fragment запрещён, например при определении базового URI для последующего разрешения относительных ссылок.

Как http(s)-URL первая строка раскладывается так:

Компонент Значение
scheme https
host example.test
path /a
query x=1
fragment part

Authority по документации MDN — секция после схемы и перед путём; она может содержать до трёх частей: user information, host и port. Path — секция после authority, данные обычно организованы иерархически. Query — секция после пути, неиерархические данные. Fragment — необязательная часть в конце, начинается с символа # и указывает на конкретную часть ресурса, например раздел документа или позицию в видео.

По RFC 3986 fragment не участвует в scheme-specific обработке: он отделяется от остального URI до dereference и обрабатывается агентом пользователя. Использование fragment не означает, что действие извлечения вообще произойдёт.

Разрешение относительных ссылок от базы

База задана: https://example.test/docs/start. Разрешаем две относительные ссылки.

Третья строка /help?q=2 — relative-ref, а именно absolute-path reference: она начинается с одного слэша. По RFC 3986 relative-ref состоит из relative-part, необязательных query и fragment. Варианты relative-part: // с authority и путём path-abempty, абсолютный путь, путь без схемы или пустой путь. Правило path-abempty допускает пустой путь и путь из сегментов, начинающихся со слэша. Ссылка с одним ведущим слэшем называется absolute-path reference. При разрешении от базы путь заменяется целиком, authority и схема берутся из базы:

ТЕКСТ
/help?q=2  →  https://example.test/help?q=2

Четвёртая строка ../img/a.png — relative-ref, relative-path reference: она не начинается со слэша. Сначала относительный путь присоединяется к каталогу базы: /docs/ и ../img/a.png дают /docs/../img/a.png. Затем алгоритм удаления точечных сегментов убирает .. вместе с предшествующим сегментом docs, и получается /img/a.png.

ТЕКСТ
../img/a.png  →  https://example.test/img/a.png

Обе ссылки разрешены от одной базы, и результат проверяем построчно. Ссылка с абсолютным путём сохраняет хост базы, ссылка с относительным путём поднимается на уровень выше. Этот эталон годится как минимальный тест: если инструмент даёт другие строки, сначала проверьте операцию разрешения ссылки и использованную базу.

Отрицательный случай 1bad:thing

Пятая строка 1bad:thing не проходит правило схемы. По грамматике RFC 3986 имя схемы начинается с буквы: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ). Первый символ здесь — цифра, поэтому строка не является URI.

Второй барьер — правило первого сегмента. Строка не является и path-noscheme: по RFC 3986 сегмент пути, содержащий двоеточие, не может быть первым сегментом relative-path reference, поскольку его приняли бы за имя схемы. Такой сегмент требуется предварять точечным сегментом, например ./this:that, чтобы получить relative-path reference. Здесь двоеточие стоит в первом сегменте, а ведущей точки нет.

Строка 1bad:thing не соответствует ни URI со схемой, ни relative-ref в исходном виде. Если добавить ./, получится ./1bad:thing — relative-ref с путём, содержащим двоеточие. При начале с буквы строку с двоеточием сначала проверяют как URI со схемой; сама эта форма не означает отказ. Для интерпретации такого первого сегмента именно как относительного пути его предваряют ./. Отрицательный случай в наборе проверяет ожидаемый отказ вместе с успешными примерами.

Fragment и HTTP request target в форме origin-form

Fragment не попадает в HTTP request target в форме origin-form. Для первой строки в target входит /a?x=1, а часть #part в него не входит.

Причина в роли fragment. По RFC 3986 fragment отделяется от остального URI до dereference и обрабатывается агентом пользователя, независимо от схемы. Он не используется в scheme-specific обработке URI. Это отличает его от path и query, которые участвуют в формировании запроса.

Практический вывод для проверки: если инструмент показывает fragment внутри request target, он смешал клиентскую и серверную части адреса. Проверка формулируется так: взять первую строку, получить target и убедиться, что он равен /a?x=1. Ожидаемый результат — fragment отсутствует. Такая проверка ловит ошибку на стыке разбора и отправки запроса, где чаще всего и теряется граница между компонентами.

План проверки читателя

План отделён от чьего-либо выполненного опыта: это последовательность действий, которую читатель проходит сам.

  1. Взять пять строк набора без изменений и записать их в файл или таблицу.
  2. Для каждой строки определить, является ли она URI или relative-ref по правилу схемы.
  3. Для первой строки восстановить scheme, host, path, query и fragment и сверить с эталоном.
  4. Для третьей и четвёртой строк применить базу https://example.test/docs/start и сверить результаты разрешения.
  5. Для пятой строки зафиксировать причину отказа: правило схемы и правило первого сегмента.
  6. Для первой строки получить HTTP request target в форме origin-form и убедиться, что fragment в него не входит.
  7. Заполнить матрицу выбора под свою задачу и отметить неизвестное.

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

Частые вопросы

Чем URI отличается от URL?

По RFC 3986 URL — подмножество URI, у которого есть средство locating: описание основного механизма доступа, например сетевого расположения. URI — более общий термин, охватывающий и имена, и локаторы. RFC 3986 рекомендует будущим спецификациям использовать общий термин URI. WHATWG, в свою очередь, фиксирует термин URL и заявляет, что на практике для URI и IRI используется один алгоритм.

Что такое urn:isbn:9780131103627 в наборе?

Это абсолютный URI с допустимой схемой urn. Схема начинается с буквы, поэтому правило схемы пройдено. Host у этой строки отсутствует: наличие host не утверждается для любой схемы, а требование host относится к выбранным http(s)-примерам. URN исторически обозначает идентификаторы, обязанные оставаться глобально уникальными и постоянными.

Почему 1bad:thing не проходит проверку?

Строка начинается с цифры, а имя схемы по грамматике RFC 3986 начинается с буквы. Второй барьер — правило первого сегмента: сегмент с двоеточием не может быть первым сегментом relative-path reference, поскольку его приняли бы за имя схемы. Такой сегмент требуется предварять точечным сегментом. Отказ приходит по правилу схемы.

Попадает ли fragment в HTTP-запрос?

Fragment не попадает в HTTP request target в форме origin-form. Для первой строки в target входит /a?x=1. По RFC 3986 fragment отделяется от остального URI до dereference и обрабатывается агентом пользователя, независимо от схемы, и не используется в scheme-specific обработке. Если инструмент показывает fragment в target, он смешал клиентскую и серверную части адреса.

Какую рамку выбрать для проверки адресов?

Если нужна строгая проверка общего синтаксиса — рамка RFC 3986. Если нужно поведение web-парсера — рамка WHATWG. Если нужен только разбор компонентов для http(s) — достаточно выбранного примера. Неизвестным остаётся поведение конкретных реализаций за пределами этих рамок. Рекомендация пересматривается при смене требований к строгости или к среде разбора.

Читайте также

3 материала