Автор оригинала: Eugen Paraschiv.
Обнаружение API REST и HATEOAS
1. Обзор
Эта статья будет посвящена Обнаружение API REST, HATEOAS и практические сценарии, обусловленные испытаниями.
2. Зачем делать API обнаруживаемым
Обнаружение API является темой, которая не получает достаточного заслуженного внимания. Как следствие, очень немногие API получают это право. Это также то, что, если все сделано правильно, может сделать API не только RESTful и использовать, но и элегантный.
Чтобы понять обнаруживаемость, мы должны понять ограничение Hypermedia As The Engine Of Application State (HATEOAS). Это ограничение REST API о полной обнаружении действий/переходов на ресурсе от Hypermedia (Hypertext действительно), как только водитель состояния применения.
Если взаимодействие должно управляться API через сам разговор, конкретно через Hypertext, то не может быть никакой документации. Это заставило бы клиента делать предположения, которые на самом деле находятся вне контекста API.
В заключение, сервер должен быть достаточно описательным, чтобы проинструктировать клиента, как использовать API только через Гипертекст. В случае разговора http, мы могли бы достичь этого через Ссылка заголовок.
3. Сценарии обнаружения (управляемые тестами)
Так что же значит для обслуживания REST быть обнаруживаемым?
На протяжении всего этого раздела мы будем тестировать индивидуальные черты обнаруживаемости с помощью Junit, гарантированный отдых и Хамкрест . С служба REST ранее была обеспечена , каждый тест сначала должен аутентификация перед потреблением API.
3.1. Откройте для себя действительные методы HTTP
Когда служба REST потребляется с помощью недействительного метода HTTP, ответ должен быть 405 METHOD NOT ALLOWED.
API также должен помочь клиенту обнаружить действительные методы HTTP, которые разрешены для этого конкретного ресурса. Для этого, мы можем использовать Разрешить HTTP Заголовок в ответе:
@Test public void whenInvalidPOSTIsSentToValidURIOfResource_thenAllowHeaderListsTheAllowedActions(){ // Given String uriOfExistingResource = restTemplate.createResource(); // When Response res = givenAuth().post(uriOfExistingResource); // Then String allowHeader = res.getHeader(HttpHeaders.ALLOW); assertThat( allowHeader, AnyOf.anyOf( containsString("GET"), containsString("PUT"), containsString("DELETE") ) ); }
3.2. Откройте для себя УРИ вновь созданного ресурса
Работа по созданию нового ресурса всегда должна включать URI вновь созданного ресурса в ответ. Для этого мы можем использовать Расположение ЗАголовок HTTP.
Теперь, если клиент делает GET на этом URI, ресурс должен быть доступен:
@Test public void whenResourceIsCreated_thenUriOfTheNewlyCreatedResourceIsDiscoverable() { // When Foo newResource = new Foo(randomAlphabetic(6)); Response createResp = givenAuth().contentType("application/json") .body(unpersistedResource).post(getFooURL()); String uriOfNewResource= createResp.getHeader(HttpHeaders.LOCATION); // Then Response response = givenAuth().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .get(uriOfNewResource); Foo resourceFromServer = response.body().as(Foo.class); assertThat(newResource, equalTo(resourceFromServer)); }
Тест следует простому сценарию: создание нового Фу ресурс, а затем с помощью ответа HTTP, чтобы обнаружить URI, где ресурс теперь доступен . Он также делает GET на том URI для того чтобы retrieve ресурс и сравнивает его к оригиналу. Это необходимо для того, чтобы убедиться, что он был правильно сохранен.
3.3. Откройте для себя URI, чтобы получить все ресурсы такого типа
Когда мы получаем какой-либо конкретной Фу ресурс, мы должны быть в состоянии узнать, что мы можем сделать дальше: мы можем перечислить все доступные Фу ресурсы. Таким образом, работа по извлечению ресурса всегда должна включать в свой ответ URI, где получить все ресурсы такого типа.
Для этого мы можем снова использовать Ссылка заголовок:
@Test public void whenResourceIsRetrieved_thenUriToGetAllResourcesIsDiscoverable() { // Given String uriOfExistingResource = createAsUri(); // When Response getResponse = givenAuth().get(uriOfExistingResource); // Then String uriToAllResources = HTTPLinkHeaderUtil .extractURIByRel(getResponse.getHeader("Link"), "collection"); Response getAllResponse = givenAuth().get(uriToAllResources); assertThat(getAllResponse.getStatusCode(), is(200)); }
Обратите внимание, что полный низкоуровневый код для extractURIByRel – ответственный за извлечение ИРИС rel отношения показано здесь .
Этот тест охватывает тернистый вопрос ссылка отношений в REST: URI для получения всех ресурсов использует rel'”сборник” семантика.
Этот тип связи еще не стандартизирован, но уже в использовании несколькими микроформатами и предлагается для стандартизации. Использование нестандартных связей открывает дискуссию о микроформатах и более богатой семантике в веб-сервисах RESTful.
4. Другие потенциальные обнаруживаемые УРИ и микроформаты
Другие УРИ потенциально могут быть обнаружены с помощью Ссылка заголовок , но есть только так много существующих типов связей позволяют, не переходя к более богатой семантической разметки, такие как определение пользовательских отношений связи , Atom Издательский протокол или микроформаты , которая будет темой другой статьи.
Например, клиент должен иметь возможность обнаружить URI для создания новых ресурсов при выполнении ПОЛУЧИТЬ на определенном ресурсе. К сожалению, нет никакой связи с моделью создать семантика.
К счастью, это стандартная практика, что URI для создания так же, как URI, чтобы получить все ресурсы такого типа, с той лишь разницей, что метод POST HTTP.
5. Заключение
Мы видели как REST API полностью обнаруживается из корня и без предварительных знаний – это означает, что клиент может перемещаться по нему, делая GET на корень. Двигаясь вперед, все изменения состояния управляются клиентом, используя доступные и обнаруживаемые переходы, которые API REST предоставляет в представлениях (отсюда Представительный государственный трансферный ).
Эта статья охватывает некоторые черты обнаруживаемости в контексте веб-сервиса REST, обсуждая открытие метода HTTP, связь между созданием и получить, открытие URI, чтобы получить все ресурсы и т.д.
Реализация всех этих примеров и фрагментов кода доступна для более на GitHub . Это maven основе проекта, поэтому она должна быть легко импортировать и работать, как она есть.