Статьи

Обнаружение веб-службы RESTful, часть 4

Это четвертая из серии статей о настройке защищенного веб-сервиса RESTful с использованием Spring 3.1 и Spring Security 3.1 с настройкой на основе Java. Статья будет посвящена Обнаруживаемости REST API, HATEOAS и практическим сценариям, основанным на тестах.

Представляем REST Discoverability

Обнаруживаемость 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 в ответе:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
@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, ресурс должен быть доступен:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
@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 :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
@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, часть 4 от нашего партнера JCG Евгения Параскива в блоге baeldung .

Статьи по Теме :