HATEOAS: абсолютные или относительные URL? - PullRequest
75 голосов
/ 10 февраля 2010

При разработке веб-службы RESTful с использованием HATEOAS, каковы плюсы и минусы показа ссылки в виде полного URL-адреса ("http://server:port/application/customers/1234") вместо только пути (" / application / Customers / 1234 ")?

Ответы [ 9 ]

69 голосов
/ 29 августа 2013

Существует тонкая концептуальная двусмысленность, когда люди говорят «относительное ури».

По определению 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

Хитрость заключается в том, что, когда схема и полномочия опущены, сама часть «пути» может быть либо абсолютным путем (начинается с «/»), либо относительным путем без корня. Примеры:

  1. абсолютный URI или полный URI: "http://example.com:8042/over/there?name=ferret"
  2. И это относительный uri с абсолютным путем : "/ over / there"
  3. И это относительный uri, с относительным путем : "здесь" или "./here" или "../here" или т. Д.

Таким образом, если вопрос заключался в том, «должен ли сервер выдавать относительный путь в ответе покоя», ответ «Нет», и здесь подробно указана причина . Я думаю, что большинство людей (включая меня) против «относительного ури» на самом деле против «относительного пути».

И на практике большая часть серверной инфраструктуры MVC может легко генерировать относительный URI с абсолютным путем , например, "/ absolute / path / to / the / controller", и возникает вопрос "является ли сервер реализация должна иметь префикс схемы: // имя_хоста: порт перед абсолютным путем ". Как и вопрос ОП. Я не совсем уверен в этом.

С одной стороны, я все еще думаю, что сервер, возвращающий полный URI, рекомендуется. Однако сервер никогда не должен жестко кодировать имя хоста: порт в исходном коде, как этот (иначе я бы предпочел откат к относительному URI с абсолютным путем). Решение на стороне сервера всегда получать этот префикс из заголовка «Host» HTTP-запроса. Не уверен, что это работает для всех ситуаций.

С другой стороны, клиенту не составит труда объединить "http://example.com:8042" и абсолютный путь. Ведь клиенту уже известны эта схема и доменное имя, когда он отправляет запрос на сервер, верно?

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

12 голосов
/ 11 февраля 2010

Это зависит от того, кто пишет код клиента. Если вы пишете клиент и сервер, это не имеет большого значения. Вы либо будете страдать от создания URL-адресов на клиенте или на сервере.

Однако, если вы создаете сервер и ожидаете, что другие люди напишут код клиента, они будут любить вас гораздо больше, если вы предоставите полные URI. Разрешение относительных URI может быть немного сложнее. Первый способ их решения зависит от типа возвращаемого носителя. Html имеет базовый тег, Xml может иметь теги xml: base в каждом вложенном элементе, каналы Atom могут иметь базу в канале и другую базу в контенте. Если вы не предоставляете своему клиенту явную информацию о базовом URI, тогда он должен получить базовый URI из URI запроса или, возможно, из заголовка Content-Location! И остерегайтесь этой косой черты. Базовый URI определяется игнорированием всех символов справа от последней косой черты. Это означает, что завершающий слеш теперь очень важен при разрешении относительных URI.

Единственная проблема, требующая небольшого упоминания, - это размер документа. Если вы возвращаете большой список элементов, где каждый элемент может иметь несколько ссылок, использование абсолютных URL-адресов может добавить значительное количество байтов вашей сущности, если вы не сжимаете сущность. Это проблема, и вам нужно решить, является ли она значимой в каждом конкретном случае.

11 голосов
/ 10 февраля 2010

Единственная реальная разница, по-видимому, заключается в том, что клиентам проще, если они используют абсолютные URI, а не создают их из относительной версии. Конечно, этой разницы будет достаточно, чтобы заставить меня сделать абсолютную версию.

7 голосов
/ 23 ноября 2011

По мере масштабирования приложения может потребоваться балансировка нагрузки, отработка отказа и т. Д. Если вы вернете абсолютные URI, тогда ваши клиентские приложения будут следовать изменяющейся конфигурации серверов.

4 голосов
/ 20 мая 2015

Используя Трихотомию РейЛоу , моя организация сделала выбор в пользу (2). Основная причина заключается в том, чтобы избежать атак XSS (межсайтовый скриптинг). Проблема в том, что если злоумышленник может внедрить свой собственный корень URL-адреса в ответ, возвращаемый с сервера, то последующие пользовательские запросы (например, запрос аутентификации с использованием имени пользователя и пароля) могут быть перенаправлены на собственный сервер злоумышленника *.

Некоторые подняли вопрос о возможности перенаправления запросов на другие серверы для балансировки нагрузки, но (хотя это не моя область знаний), я бы держал пари, что существуют более эффективные способы включения балансировки нагрузки без необходимости явного перенаправления клиенты на разных хостах.

*, пожалуйста, дайте мне знать, если есть какие-либо недостатки в этой аргументации. Цель, конечно, не в том, чтобы предотвратить все атаки, а как минимум в одном направлении атаки.

3 голосов
/ 04 октября 2013

Вы всегда должны использовать полный URL. Он действует как уникальный идентификатор ресурса, поскольку все URL-адреса должны быть уникальными.

Я бы также сказал, что вы должны быть последовательными. Поскольку HTTP-заголовок Location ожидает полный URL-адрес на основе спецификации HTTP, полный URL-адрес отправляется обратно в заголовок Location клиенту при создании нового ресурса. Было бы странно, если бы вы указали полный URL-адрес в заголовке «Местоположение», а затем относительные URI-адреса в ссылках в теле ответа.

2 голосов
/ 26 ноября 2012

Одним из недостатков использования абсолютных URI является то, что API не может быть прокси.

Забери это обратно ... не правда. Вы должны перейти на полный URL, включая домен.

1 голос
/ 10 мая 2019

Относительно плюсов, я вижу сокращение байтов, которые должны быть переданы за счет дополнительной обработки, требуемой клиентом для (абсолютного) пути. Если вы отчаянно пытаетесь сохранить каждый байт, даже после попытки кодирования содержимого в виде gzip, правильного использования заголовков кэширования, использования etags и условных запросов на клиенте, тогда это может быть необходимо в конце, но я ожидаю гораздо более высокую отдачу от ваши усилия были еще.

Что касается минусов, я вижу потерю контроля над тем, как вы можете направить поток клиентов между ресурсами в будущем (балансировка нагрузки, A / B-тестирование, ...), и я бы посчитал это плохой практикой в ​​отношении управление веб-API. Предоставленный вами URL больше не является непрозрачным для клиента (см. Тим Бернерс-Ли Аксиомы веб-архитектуры о непрозрачности URI ). В конце концов, вы берете на себя ответственность за то, чтобы клиенты были довольны творческим использованием вашего API, даже если это касается только структуры вашего URL-пространства. Если вам когда-либо понадобится разрешить явно заданную модификацию URL, рассмотрите возможность использования шаблонов URI , которые используются в языке гипертекстовых приложений .

1 голос
/ 24 января 2014

Важным фактором при больших результатах API является дополнительная нагрузка на сеть, связанная с повторным включением полного URI. Верьте или нет, gzip не полностью решает эту проблему (не знаю почему). Мы были шокированы тем, сколько места занял полный URI, когда в результат были включены сотни ссылок.

...