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

RESTful api design, HATEOAS и обнаружение ресурсов

Одной из основных идей, лежащих в основе HATEOAS, является то, что клиенты должны иметь возможность начинать с URL единой точки входа и обнаруживать все открытые ресурсы и переходы состояний, доступные для них. Хотя я прекрасно понимаю, как это работает с HTML и человеком за браузером, нажимая на ссылки и кнопки "Отправить", я спрашиваю о том, как этот принцип может быть применен к проблемам, с которыми мне (не) повезло иметь дело.

Мне нравится, как принцип дизайна RESTful представлен в документах и ​​учебных статьях, где все имеет смысл, Как получить чашку кофе - хороший пример. Я попытаюсь следовать конвенции и придумаю пример, который прост и свободен от утомительных деталей. Давайте посмотрим на почтовые индексы и города.

Проблема 1

Скажем, я хочу создать RESTful api для поиска городов по почтовым индексам. Я придумываю ресурсы, называемые "городами", вложенными в почтовые индексы, поэтому GET на http://api.addressbook.com/zip_codes/02125/cities возвращает документ, содержащий, скажем, две записи, которые представляют собой Дорчестер и Бостон.

Мой вопрос: каким образом этот url может быть обнаружен через HATEOAS? Вероятно, нецелесообразно выставлять индекс всех ~ 40K почтовых индексов под http://api.addressbook.com/zip_codes. Даже если у вас нет проблем с индексом 40K, помните, что я сделал этот пример, и там есть коллекции гораздо большей величины.

По сути, я бы хотел разоблачить не ссылку, а шаблон ссылки, а именно: http://api.addressbook.com/zip_codes/{:zip_code}/cities, и это противоречит принципам и зависит от внеполосных знаний, которыми обладает клиент.

Проблема 2

Предположим, что хочу показать индекс города с определенными возможностями фильтрации:

  • GET on http://api.addressbook.com/cities?name=X будет возвращать только города с именами, соответствующими X.

  • GET on http://api.addressbook.com/cities?min_population=Y приведет только к возврату городов с населением, равным или большим, чем Y.

Конечно, эти два фильтра могут использоваться вместе: http://api.addressbook.com/cities?name=X&min_population=Y.

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

Итак, как принципы HATEOAS могут помочь сделать такой тривиальный API действительно RESTful?

4b9b3361

Ответ 1

Я предлагаю использовать формы XHTML:

GET /

HTTP/1.1 OK

<form method="get" action="/zip_code_search" rel="http://api.addressbook.com/rels/zip_code_search">
   <p>Zip code search</p>
   <input name="zip_code"/>
</form>

GET /zip_code_search?zip_code=02125

HTTP/1.1 303 See Other
Location: /zip_code/02125

То, что отсутствует в HTML, является атрибутом rel для form.

Отметьте в этой статье:

Подводя итог, есть несколько причин рассматривать XHTML как представление по умолчанию для ваших служб RESTful. Во-первых, вы можете использовать синтаксис и семантику для важных элементов, таких как <a>, <form> и <input> вместо того, чтобы изобретать свои собственные. Во-вторых, вы закончите с услугами, которые очень похожи на сайты, потому что они будут просматриваемых как пользователями, так и приложениями. XHTML по-прежнему интерпретируется человеком - это просто программист во время разработки вместо пользователя во время выполнения. Это упрощает процесса разработки и облегчает пользователям узнавать, как ваш сервис работает. И, наконец, вы можете использовать стандартный веб-интерфейс для создания ваших сервисов RESTful.

Также проверьте OpenSearch.

<ч/" > Чтобы уменьшить число запросов, рассмотрите этот ответ:

HTTP/1.1 200 OK
Content-Location: /zip_code/02125

<html>
<head>
<link href="/zip_code/02125/cities" rel="related http://api.addressbook.com/rels/zip_code/cities"/>
</head>
...
</html>

Ответ 2

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

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <grammars/>
  <resources base="http://localhost:8080/cities">
    <resource path="/">
      <method name="GET">
        <request>
          <param name="name" style="query" type="xs:string"/>
          <param name="min-population" style="query" type="xs:int"/>
        </request>
        <response>
          <representation mediaType="application/octet-stream"/>
        </response>
      </method>
    </resource>
  </resources>
</application>

Этот пример был автогенерирован CXF из этого Java-кода:

import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

public class Cities {
    @GET
    public Response get(@QueryParam("name") String name, @QueryParam("min-population") int min_poulation) {
        // TODO: build the real response
        return Response.ok().build();
    }
}

Ответ 3

В ответ на вопрос 1 я предполагаю, что ваша единственная точка входа http://api.addressbook.com/zip_codes, и намерение состоит в том, чтобы позволить клиенту перемещаться по всему набору почтовых индексов и в конечном итоге извлекать города, связанные с ними.

В этом случае я вернул бы ресурс http://api.addressbook.com/zip_codes для перенаправления на первую страницу почтовых индексов, например:

http://api.addressbook.com/zip_codes?start=0&end=xxxx

Это будет содержать ссылки на почтовые индексы "страницы" (любой номер подходит для обрабатываемой системы, а также ссылка на следующую страницу (и предыдущую страницу, если она есть).

Это позволит клиенту обходить весь список почтовых индексов, если это необходимо.

URL-адреса, возвращаемые на каждой странице, будут выглядеть примерно так:

http://api.addressbook.com/zip_codes/02125

И тогда было бы вопросом, включать ли городскую информацию в представление, возвращаемое URL-адресом почтового индекса, или ссылку на него в зависимости от необходимости.

Теперь у клиента есть выбор: пройти ли весь список почтовых индексов, а затем запросить zipcode (а затем и города) для каждого или запросить страницу почтовых индексов, а затем запросить разворот до parti

Ответ 4

Я столкнулся с этими же вопросами - поэтому я работал на практическом примере, который решает обе эти проблемы (и некоторые из них вы еще не задумывались). http://thereisnorightway.blogspot.com/2012/05/api-example-using-rest.html?m=1

В принципе, решение проблемы 1 заключается в том, что вы меняете свое представление (как говорит Рой, тратьте время на ресурс). Вам не нужно возвращать все почтовые индексы, просто сделайте свой ресурс пейджинговым. Например, когда вы запрашиваете новостные страницы на новостном сайте - это дает вам сегодняшние новости и ссылки на другие, даже если все статьи могут жить под одной и той же структурой URL-адреса.... статья /123 и т.д.

Проблема 2 немного противоположна - в http называется OPTIONS, которую я использовал в примере, чтобы в основном отражать возможности URL-адреса, хотя в этом представлении вы могли бы решить эту проблему, это будет просто сложнее. В принципе, он возвращает настраиваемую структуру, которая показывает возможности ресурса (включая необязательные параметры).

Дайте мне знать, что вы думаете!

Ответ 5

Я чувствую, что вы пропустили URL-адрес закладки. Это первый URL-адрес, а не тот, который позволяет получать города или почтовые индексы.

Итак, вы начинаете с ab: = http://api.addressbook.com

Эта первая ссылка возвращает список доступных ссылок. Так работает Интернет. Вы заходите на сайт www.yahoo.com, а затем начинаете нажимать ссылки, не зная, куда они идут.

Итак, из исходной ссылки ab: вы вернетесь к другим ссылкам, и у них могут быть ссылки REL, которые объясняют, как эти ресурсы должны быть доступны или какие параметры могут быть отправлены.

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

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