Это четвертая серия статей о настройке защищенного веб-сервиса RESTful с использованием Spring 3.1 и Spring Security 3.1 с настройкой на основе Java. Статья будет посвящена Обнаруживаемости REST API, HATEOAS и практическим сценариям, основанным на тестах.
ОТДЫХ с весенней серией:
- Часть 1 — Бутстрапирование веб — приложений с Spring 3.1 и Java на основе конфигурации
- Часть 2 — Создание веб — службы RESTful с Spring 3.1 и Java на основе конфигурации
- Часть 3 — Обеспечение безопасности веб — службы RESTful с Spring Security 3.1
- Часть 5 — REST Service Discoverability с весной
- Часть 6. Базовая и дайджест-проверка подлинности для службы RESTful с Spring Security 3.1
- Часть 7. REST Pagination весной
- Часть 8 — Аутентификация против службы RESTful с Spring Security
- Часть 9 — ETAG для отдыха с пружиной
Представляем REST Discoverability
D iscoverability из API является тема , которая не получает достаточно хорошо заслуженное внимание, и как следствие очень мало API , чтобы это право. Это также то, что, если все сделано правильно, может сделать API не только RESTful и удобным, но и элегантным.
Чтобы понять обнаруживаемость , нужно понять это ограничение, которое является гипермедиа как движок состояния приложения (HATEOAS); это ограничение API RESTful касается полной возможности обнаружения действий / переходов на ресурсе из гипермедиа (действительно, гипертекст), как единственного драйвера состояния приложения. Если взаимодействие будет приводится в API через сам разговор, конкретно через гипертекст, то не может быть никакой документации , поскольку это будет принуждать клиент сделать предположение, которые на самом деле за пределы контексте API.
Кроме того, продолжая этот логический ход мысли, единственный способ, которым API действительно может считаться RESTful, — это если он полностью обнаруживаем из корня и без предварительного знания — это означает, что клиент должен иметь возможность перемещаться по API, выполняя GET на корень. В дальнейшем все изменения состояния осуществляются клиентом с использованием доступных и обнаруживаемых переходов, которые REST API предоставляет в представлениях (отсюда передача состояния представлений ).
В заключение, сервер должен быть достаточно информативным, чтобы указывать клиенту, как использовать API только через гипертекст, который, в случае HTTP-разговора, может быть заголовком Link .
Конкретные сценарии обнаружения (управляемые тестами)
Так что же означает, что служба REST может быть обнаружена ? В этом разделе мы будем тестировать отдельные признаки обнаруживаемости, используя Junit, rest-assured и Hamcrest . Поскольку служба REST была защищена в части 3 серии , каждый тест должен сначала пройти аутентификацию перед использованием API. Некоторые утилиты для анализа заголовка ссылки ответа также необходимы.
Откройте для себя действительные методы HTTP
Когда веб-служба RESTful используется с недопустимым методом HTTP , ответ должен быть 405 МЕТОД НЕ РАЗРЕШЕН ; Кроме того, это также должно помочь клиенту найти допустимые методы HTTP, которые разрешены для этого конкретного ресурса, используя заголовок Allow HTTP в ответе:
@Test public void whenInvalidPOSTIsSentToValidURIOfResource_thenAllowHeaderListsTheAllowedActions(){ // Given final String uriOfExistingResource = this.restTemplate.createResource(); // When Response res = this.givenAuthenticated().post( uriOfExistingResource ); // Then String allowHeader = res.getHeader( HttpHeaders.ALLOW ); assertThat( allowHeader, AnyOf.<String> anyOf( containsString("GET"), containsString("PUT"), containsString("DELETE") ) ); }
Откройте для себя URI вновь созданного ресурса
Операция создания нового ресурса всегда должна включать в ответ URI вновь созданного ресурса с использованием заголовка HTTP местоположения . Если клиент выполняет GET для этого URI, ресурс должен быть доступен:
@Test public void whenResourceIsCreated_thenURIOfTheNewlyCreatedResourceIsDiscoverable(){ // When Foo unpersistedResource = new Foo( randomAlphabetic( 6 ) ); Response createResponse = this.givenAuthenticated().contentType( MIME_JSON ) .body( unpersistedResource ).post( this.paths.getFooURL() ); final String uriOfNewlyCreatedResource = createResp .getHeader( HttpHeaders.LOCATION ); // Then Response response = this.givenAuthenticated() .header( HttpHeaders.ACCEPT, MIME_JSON ).get( uriOfNewlyCreatedResource ); Foo resourceFromServer = response.body().as( Foo.class ); assertThat( unpersistedResource, equalTo( resourceFromServer ) ); }
Тест проводится по простому сценарию: создается новый ресурс Foo, а HTTP-ответ используется для обнаружения URI, где теперь доступен ресурс. Затем тесты продвигаются на один шаг вперед и выполняют GET для этого URI, чтобы извлечь ресурс и сравнить его с оригиналом, чтобы убедиться, что он был правильно сохранен.
Откройте для себя URI, чтобы получить все ресурсы этого типа
Когда мы ПОЛУЧАЕМ конкретный экземпляр Foo , мы должны иметь возможность узнать, что мы можем делать дальше: мы можем перечислить все доступные ресурсы Foo . Таким образом, операция извлечения ресурса всегда должна включать в свой ответ URI, где получить все ресурсы этого типа, снова используя заголовок Link :
@Test public void whenResourceIsRetrieved_thenURIToGetAllResourcesIsDiscoverable(){ // Given String uriOfExistingResource = this.restTemplate.createResource(); // When Response getResponse = this.givenAuthenticated().get( uriOfExistingResource ); // Then String uriToAllResources = HTTPLinkHeaderUtils.extractURIByRel ( getResponse.getHeader( "Link" ), "collection" ); Response getAllResponse = this.givenAuthenticated().get( uriToAllResources ); assertThat( getAllResponse.getStatusCode(), is( 200 ) ); }
Тест затрагивает сложную тему отношений связей в REST: URI для извлечения всех ресурсов использует семантику rel = ”collection” . Этот тип связи еще не стандартизирован, но уже используется несколькими микроформатами и предлагается для стандартизации. Использование нестандартных отношений ссылок открывает дискуссию о микроформатах и более богатой семантике в веб-сервисах RESTful.
Другие потенциальные обнаруживаемые URI и микроформаты
Другие URI потенциально могут быть обнаружены через заголовок Link , но существует только столько, сколько позволяют существующие типы отношений ссылок без перехода к более богатой семантической разметке, такой как определение пользовательских отношений ссылок , протокол публикации Atom или микроформаты , которые будут темой другой статьи.
Например, было бы хорошо, если бы клиент мог обнаружить URI для создания новых ресурсов при выполнении GET для определенного ресурса; к сожалению, нет никакого отношения ссылки к семантике создания модели . К счастью, стандартная практика заключается в том, что URI для создания такой же, как и URI для получения всех ресурсов этого типа, с единственным отличием — это метод POST HTTP.
Вывод
В этой статье были рассмотрены некоторые признаки обнаруживаемости в контексте веб-службы RESTful, обсуждается обнаружение методов HTTP, связь между созданием и получением, обнаружением URI для получения всех ресурсов и т. Д. В следующих статьях я сосредоточусь на обнаружение API, начиная с корня , разбиения на страницы, пользовательских отношений ссылок, протокола публикации Atom и фактической реализации Discoverability в службе REST с помощью Spring. В то же время, проверьте проект GitHub .
Если вы читаете это далеко, вы должны следовать за мной в твиттере здесь .
Оригинал на веб-сервисе RESTful Обнаружение от REST с серией Spring .