Подтвердить что ты не робот

HATEOAS: абсолютные или относительные URL-адреса?

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

4b9b3361

Ответ 1

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

В определение 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" или "../here" и т.д.

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

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