Когда люди говорят «относительный URI», возникает тонкая концептуальная двусмысленность.
По определению RFC3986 универсальный URI содержит:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
Сложность в том, что когда схема и авторитет опущены, сама часть «пути» может быть либо абсолютным путем (начинается с /
), либо относительным путем «без корня». Примеры:
- Абсолютный URI или полный URI:
"http://example.com:8042/over/there?name=ferret"
- И это относительный uri с абсолютным путем :
/over/there
- И это относительный uri с относительным путем :
here
or ./here
or ../here
or etc.
Итак, если вопрос был в том, «должен ли сервер выдавать относительный путь в спокойном ответе», ответ будет «Нет», и подробные сведения о причине доступны здесь . Я думаю, что большинство людей (включая меня) против «относительного URI» на самом деле против «относительного пути».
И на практике большая часть серверной инфраструктуры MVC может легко сгенерировать относительный URI с абсолютным путем, например /absolute/path/to/the/controller
, и возникает вопрос, «должна ли реализация сервера префикс a scheme://hostname:port
перед абсолютным путем». Как вопрос ОП. Я не совсем уверен в этом.
С одной стороны, я по-прежнему считаю, что сервер, возвращающий полный uri, рекомендуется. Однако сервер никогда неhostname:port
должен жестко кодировать что- то внутри исходного кода, подобного этому (в противном случае я бы предпочел вернуться к относительному uri с абсолютным путем). Решение заключается в том, что серверная сторона всегда получает этот префикс из заголовка HTTP-запроса "Host". Не уверен, работает ли это для всех ситуаций.
С другой стороны, для клиента не составляет большого труда объединить http://example.com:8042
абсолютный путь и. В конце концов, клиент уже знает эту схему и доменное имя, когда отправляет запрос на сервер, верно?
В целом, я бы сказал, рекомендую использовать абсолютный URI, возможно, вернуться к относительному URI с абсолютным путем, никогда не использовать относительный путь .
Это зависит от того, кто пишет клиентский код. Если вы пишете клиент и сервер, это не имеет большого значения. Вы будете либо страдать от создания URL-адресов на клиенте, либо на сервере.
Однако, если вы создаете сервер и ожидаете, что другие люди будут писать клиентский код, они полюбят вас гораздо больше, если вы предоставите полные URI. Разрешение относительных URI может быть немного сложным. Во-первых, как вы их разрешите, зависит от возвращаемого типа носителя. Html имеет базовый тег, Xml может иметь теги xml: base в каждом вложенном элементе, фиды Atom могут иметь базу в фиде и другую базу в содержимом. Если вы не предоставляете своему клиенту явную информацию о базовом URI, он должен получить базовый URI из URI запроса или, возможно, из заголовка Content-Location! И берегитесь этой косой черты в конце. Базовый URI определяется путем игнорирования всех символов справа от последней косой черты. Это означает, что завершающая косая черта теперь очень важна при разрешении относительных URI.
Единственная другая проблема, требующая небольшого упоминания, - это размер документа. Если вы возвращаете большой список элементов, каждый из которых может иметь несколько ссылок, использование абсолютных URL-адресов может добавить значительное количество байтов к вашей сущности, если вы не сжимаете сущность. Это проблема производительности, и вам нужно решать, имеет ли она значение в каждом конкретном случае.
источник
Единственная реальная разница, казалось бы, заключается в том, что клиентам проще использовать абсолютные URI вместо того, чтобы создавать их из относительной версии. Конечно, этой разницы было бы достаточно, чтобы заставить меня сделать абсолютную версию.
источник
По мере масштабирования приложения вы можете выполнять балансировку нагрузки, переключение при отказе и т. Д. Если вы возвращаете абсолютные URI, ваши клиентские приложения будут следовать вашей развивающейся конфигурации серверов.
источник
/xxx/yyy...
), а не как означающий полный URI (напримерhttp://api.example.com/xxx/yyy...
).Используя трихотомию RayLou, моя организация предпочла (2). Основная причина - избежать атак XSS (межсайтовый скриптинг). Проблема в том, что если злоумышленник может ввести свой собственный URL-адрес в ответ, возвращаемый с сервера, то последующие запросы пользователей (например, запрос аутентификации с именем пользователя и паролем) могут быть перенаправлены на собственный сервер злоумышленника *.
Некоторые поднимали вопрос о возможности перенаправлять запросы на другие серверы для балансировки нагрузки, но (хотя это не моя область знаний) я бы поспорил, что есть лучшие способы включить балансировку нагрузки без необходимости явно перенаправлять клиентов на разные хосты.
* пожалуйста, дайте мне знать, есть ли какие-либо недостатки в этой аргументации. Цель, конечно, не в том, чтобы предотвратить все атаки, а в том, чтобы предотвратить хотя бы одно направление атаки.
источник
Вы всегда должны использовать полный URL. Он действует как уникальный идентификатор ресурса, поскольку все URL-адреса должны быть уникальными.
Я также считаю, что вы должны быть последовательны. Поскольку HTTP-заголовок Location ожидает полный URL-адрес на основе спецификации HTTP, полный URL-адрес отправляется обратно клиенту в заголовке Location при создании нового ресурса. Было бы странно указывать полный URL-адрес в заголовке Location, а затем относительные URI в ссылках в теле ответа.
источник
Location
дает пример заголовка спецификации - абсолютный URI, который не содержит схему URI или сетевое местоположение сервера. Хотя ссылки и идентификаторы часто объединяются, это не одно и то же - первые имеют контекст, а вторые - нет.Важное соображение в больших результатах API - это дополнительные сетевые издержки, связанные с повторным включением полного URI. Вы не поверите, но gzip не решает полностью эту проблему (не знаю почему). Мы были шокированы тем, сколько места занимал полный URI, когда в результат включались сотни ссылок.
источник
Один из недостатков использования абсолютных URI заключается в том, что API нельзя проксировать.Верни это ... неправда. Вам следует выбрать полный URL-адрес, включая домен.
источник
Что касается плюсов, я вижу сокращение количества передаваемых байтов за счет дополнительной обработки, необходимой клиенту для (абсолютного) пути. Если вы отчаянно пытаетесь сохранить каждый байт, даже после попытки кодирования содержимого как gzip, правильного использования заголовков кеширования, использования etags и условных запросов на клиенте, то в конечном итоге это может потребоваться, но я ожидаю гораздо более высокой отдачи от ваши усилия были другими.
Что касается минусов, я вижу потерю контроля в отношении того, как вы можете направлять поток клиентов между ресурсами в будущем (балансировка нагрузки, A / B-тестирование, ...), и я бы счел это плохой практикой в отношении управления сетью. API. Предоставляемый вами URL-адрес больше не является непрозрачным для клиента (см. Аксиомы веб-архитектуры Тима Бернерса-Ли о непрозрачности URI ). В конце концов, вы берете на себя ответственность за то, чтобы клиенты были довольны своим творческим использованием вашего API, даже если это касается только структуры вашего URL-пространства. Если вам когда-нибудь понадобится разрешить явно определенную модификацию URL-адреса, рассмотрите возможность использования шаблонов URI, используемых в языке гипертекстовых приложений .
источник