Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Приницы RESTful Web Services

HTTP протокол

Краткое описание HTTP протокола

Что такое HTTP протокол

HTTP (HyperText Transfer Protocol) - протокол передачи данных, который используется во Всемрной Паутине. Протокол предполагает использование клиент-серверной структуры передачи данных и определяет форматы запроса клиента и ответа сервера.

Структура запроса (GET / HTTP/1.1, Headers, Body, etc.)

Простейшая структура запроса {метод} {URI} HTTP/{версия}

GET / HTTP/1.1

Метод определяет операцию, которую нужно сделать. Их около 10, самые распространенные GET, POST.

URI определяет путь к ресурсу, над которым нужно сделать операцию.

HTTP/1.1 указывает протокол передачи данных и версию.

Так же могут передавать заголовки (Headers). Заголовки позволяют характеризовать тело сообщения, параметры передачи и пр. Например, в заголовках передается авторизация юзера (заголовок Authorization). Кроме стандартных можно создавать кастомные.

Некоторые методы позволяют передавать тело запроса (body). Например, POST. Когда вы сохраняете форму в интернете, данные попадают в тело запроса и отправляются на сервис с методом POST.

Структура ответа

Простейшая структура ответа HTTP/{Версия} {Код состояния} {Пояснение}

HTTP/1.1 200 OK

HTTP/1.1 указывает протокол передачи данных и версию.

Код состояния указывает на результат запроса. Состоит из трех цифр. Первая указывает на класс состояния.

Пояснение к коду состояния предназначено для упрощения чтения ответа человеком. Клиентами не используется.

1xx - Информационные (напр. 102 Processing).

2xx - Успех (200 OK).

3xx - Перенаправление (307 Temporary Redirect).

4xx - Ошибка клиента (404 Not Found).

5xx - Ошибка сервера (500 Internal Server Error).

Ответ так же может содержать заголовки, которые так же характеризуют тело ответа, параметры передачи и др. Например, Content-Type говорит о формате тела ответа (xml, json, тд)

Пример запроса и ответа

GET

Request:

GET http://star-wars-world.com/api/starship/22/ HTTP/1.1Host: swapi.coConnection: keep-aliveAccept: application/jsonCache-Control: no-cacheUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36Authentication: eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE0Nzk2NDAccept-Encoding: gzip, deflate, sdchAccept-Language: ru,en-US;q=0.8,en;q=0.6,pl;q=0.4Cookie: __cfduid=d1f673d4df7e6a71822a5bdc89a702c581479232563

Response:

HTTP/1.1 200 OK Date: Sun, 20 Nov 2016 10:05:34 GMTContent-Type: application/jsonConnection: keep-aliveEtag: W/"ca7104107dff4ee1865fb62324951455"X-Frame-Options: SAMEORIGINVary: Accept, CookieAllow: GET, HEAD, OPTIONSVia: 1.1 vegurServer: cloudflare-nginxCF-RAY: 304b158ec0e74f14-DMEContent-Length: 579 { "name": "Imperial shuttle", "model": "Lambda-class T-4a shuttle", "manufacturer": "Sienar Fleet Systems", "cost_in_credits": "240000", "length": "20", "max_atmosphering_speed": "850", "crew": "6", "passengers": "20", "cargo_capacity": "80000", "consumables": "2 months", "hyperdrive_rating": "1.0", "MGLT": "50", "starship_class": "Armed government transport", "pilots": [ "http://swapi.co/api/persons/1/", "http://swapi.co/api/persons/13/", "http://swapi.co/api/persons/14/" ], "created": "2014-12-15T13:04:47.235000Z", "edited": "2014-12-22T17:35:44.795405Z", "url": "http://swapi.co/api/starships/22/"}

POST

Request:POST http://star-wars-world.com/api/starship/ HTTP/1.1Host: swapi.coConnection: keep-aliveContent-Length: 295Content-Type: Application/jsonAccept: application/jsonCache-Control: no-cacheUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36Authentication: eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE0Nzk2NDAccept-Encoding: gzip, deflate, sdchAccept-Language: ru,en-US;q=0.8,en;q=0.6,pl;q=0.4Cookie: __cfduid=d1f673d4df7e6a71822a5bdc89a702c581479232563 { "name": "Star Destroyer", "model": "Imperial I-class Star Destroyer", "manufacturer": "Kuat Drive Yards", "cost_in_credits": "150000000", "length": "1,600", "max_atmosphering_speed": "975", "crew": "47060", "passengers": "0", "cargo_capacity": "36000000", "consumables": "2 years", "hyperdrive_rating": "2.0", "MGLT": "60", "starship_class": "Star Destroyer"}

Response:

HTTP/1.1 201 CreatedLocation: http://star-wars-world.com/api/starship/32/Date: Sun, 20 Nov 2016 10:05:34 GMTContent-Type: application/jsonConnection: keep-aliveEtag: W/"ca7104107dff4ee1865fb62324951455"X-Frame-Options: SAMEORIGINVary: Accept, CookieAllow: GET, HEAD, OPTIONSVia: 1.1 vegurServer: cloudflare-nginxCF-RAY: 304b158ec0e74f14-DMEContent-Length: 579

 

URL

http://star-wars-world.com:831/persons?film=1

 

Part Name Description
star-wars-world.com Hostname DNS hostname or IP address of the server. Used to setup TCP socket connection
  Port TCP socket port listened by server. Optional – if not specified then used default for protocol. E.g. 80 for http, 443 for https (see below)
persons Path Path to document. Optional
film=1 Query Request parameter(s). Optional

 


Приницы RESTful Web Services

 

REST - архитектурный стиль ПО для построения распределенных масштабируемых систем, расположенных в сети. Данная архитектура придерживается следующим принципам:

 

а) Клиент-серверная архитектура

 

б) Независимость от состояния (Statelessness)

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

 

в) Кэширование

Сервис должен обладать механизмом предоставления клиенту информации о том, что ответ сервера может быть кэширован на определенный период времени и использоваться повторно без новых запросов к серверу. Мы говорим про кэш на стороне клиента. Один из вариантов, обрабатывать заголовок запроса типа If-Modified-Since. Т.е. клиент как бы спрашивает, модифицировался ли ресурс с определенного времени. Если нет, тогда клиент не обрабатывает/ не запрашивает объекты ресурса, а отображает пользователю и своего кэша.

 

г) Единообразие интерфейса

- Идентификация ресурсов. Каждый ресурс обладает своим уникальным URI. Например: /persons/12345

 

- Манипуляция ресурсами через представление. под представлением понимается формат передаваемых данных, например JSON или XML.

 

- Самодостаточные сообщения. Каждый ответ должен содержать всю необходимую информацию, чтобы его можно было правильно обработать

 

- HATEOAS. Hypermedia As The Engine Of Application State. В каждом полученном ответе содержится ссылка на следующий запрос. Это схоже перехожу с главное страницы на другие ресурсу внутри веб приложения.

 

д) Многослойность.

Клиент может взаимодействовать не напрямую с сервером, а через промежуточные узлы

(слои). При этом клиент может не знать об их существовании

 

е) Код по требованию

 

Для расширения функциональности клиента сервер может передавать исполняемый код клиент. Например, Java-апплеты или скрипты типа JavaScript и тд.


Тестирование веб-сервисов

 

Данная глава разделена на методы. Информация, которую полезно знать и которая относится сразу ко всем методам, была внесена во введение.

Введение

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

Например, persons это ресурс. URL для работы с этим ресурсом:

 

http://star-wars-world.com/api/persons

 

Ресурсы всегда называются именами существительными (бывают исключения, но редко). Ресурсы бывают 2ух типов: коллекции и элемент коллекции. Коллекция - набор самостоятельных элементов ресурса. Элемент коллекции - объект. Например:

http://star-wars-world.com/api/persons - коллекция объектов (в данному случае, персонажей)

 

http://star-wars-world.com/api/persons/{id} - конкретный объект (в данному случае, конкретный персонаж)

 

GET

Общая информация

1. Метод GET позволяет получить объекты ресурса. Обычно ресурс имеет два URL: один для работы с коллекцией объектов, другой для работы с одним объектом.

 

Пример:

 

URL /persons предоставляет сервис для работы с коллекцией объектов. Мы обращаемся к /persons с методом GET, чтобы получить всех персонажей мира Звездных войн.

 

Request:

GET /persons

 

Response:

Status: 200 OK{ "results": [ { "id": 1, "name": "Luke Skywalker", "height": "172", "mass": "77", "hair_color": "blond", "skin_color": "fair", "eye_color": "blue", "birth_year": "19BBY", "gender": "male", "homeworld": "http://swapi.co/api/planets/1/", "species": [ "http://swapi.co/api/species/1/" ], "vehicles": [ "http://swapi.co/api/vehicles/14/", "http://swapi.co/api/vehicles/30/" ], "starships": [ "http://swapi.co/api/starships/12/", "http://swapi.co/api/starships/22/" ], "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-20T21:17:56.891000Z", "url": "http://swapi.co/api/persons/1/" }, { "id": 2, "name": "C-3PO", "height": "167", "mass": "75", "hair_color": "n/a", "skin_color": "gold", "eye_color": "yellow", "birth_year": "112BBY", "gender": "n/a", "homeworld": "http://swapi.co/api/planets/1/", "species": [ "http://swapi.co/api/species/2/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:10:51.357000Z", "edited": "2014-12-20T21:17:50.309000Z", "url": "http://swapi.co/api/persons/2/" }, { "id": 3, "name": "R2-D2", "height": "96", "mass": "32", "hair_color": "n/a", "skin_color": "white, blue", "eye_color": "red", "birth_year": "33BBY", "gender": "n/a", "homeworld": "http://swapi.co/api/planets/8/", "species": [ "http://swapi.co/api/species/2/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:11:50.376000Z", "edited": "2014-12-20T21:17:50.311000Z", "url": "http://swapi.co/api/persons/3/" },..... ]}

 

2. URL /persons/{id} предоставляет сервис для работы с одним объектом. Мы обращаемся к /persons/{id} с методом GET, чтобы получить всю информацию по объекта с указанным id.

 

Пример:

 

Request:

GET /persons/1

 

Response:

Status: 200 OK { "name": "Luke Skywalker", "height": "172", "mass": "77", "hair_color": "blond", "skin_color": "fair", "eye_color": "blue", "birth_year": "19BBY", "gender": "male", "homeworld": "http://swapi.co/api/planets/1/", "species": [ "http://swapi.co/api/species/1/" ], "vehicles": [ "http://swapi.co/api/vehicles/14/", "http://swapi.co/api/vehicles/30/" ], "starships": [ "http://swapi.co/api/starships/12/", "http://swapi.co/api/starships/22/" ], "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-20T21:17:56.891000Z"}

 

3. Если указанный в URL id (объект с таким id) не существует, веб-сервис должен вернуть ошибку, например 404 'Not Found'.

 

Пример:

Персонаж с id = 133123 отсутствует в данной системе. Отправляем запрос на получение персонажа с id = 133123

 

Request:

GET /persons/133123

Response:

Status: 404 Not Found Error: Specified object is not found.

 

4. Если запрашиваемый объект был удален, веб-сервис должен вернуть ошибку, например 301 Moved Permanently или 404 Not Found (зависит от конкретной реализации).

 

Пример:

Персонаж с id = 967 был удален. Отправляем запрос на получение персонажа id = 967.

 

Request:

GET /persons/967

Response:

Status: 301 Moved Permanently Error: Requested object has been removed.

 

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

 

Пример:

У пользователя нет доступа к персонаж с id = 364. Отправляем запрос на получение персонажа id = 364.

 

Request:

GET /persons/364

Response:

Status: 403 Forbidden Error: Requested object cannot be accessed due to security setting.

 

 

Что тестировать:

- Запросить существующий объект.

- Проверить список полученных параметров.

- Проверить все значения полученных параметров.

- Запросить несуществующий объект.

- Запросить удаленный объект.

- Запросить объект, к которому нет доступа по бизнес логике/ правам пользователя.

Страничная организация

6. Объектов и их параметров может быть очень большое количество. Например, в Звездных Войнах значимых персонажей около 100 и у каждого более 15 параметров. Ответ может быть размером несколько сотен килобайт или единиц мегабайт и его получение занимать несколько секунд. Для улучшения производительности объекты отдаются частями, как бы разбивают "на страницы". Ответы содержит часть объектов, номер страницы и ссылку на следующую страницу.

Пример:

/persons возвращает список всех персонажей. Веб-сервис возвращает по 10 объектов за 1 запрос. Ответ содержит ссылку на получение следующих 10 объектов.

 

Request:

GET /persons

 

Response:

Status: 200 OK{ "count_on_page": 10, "next": "http://swapi.co/api/persons?page=2", "previous": null, "results": [....]

 

Что тестировать:

- Количество объектов "на странице".

- Ссылка на следующую "страницу".

- Ссылка на предыдущую "страницу".

- Ссылки на "страницы" если объектов меньше максимально возможного числа на первой "странице".

Связи

7. Между ресурсами могут существовать связи. Например, персонаж может быть пилотом космических кораблей. В нашем веб-сервисе есть ресурс, который позволяет получить список всех космических кораблей (/starships).

В таком случае, связь одного объекта к другому должна быть указана в ответе в виде ссылки на объект. В нашем примере, это ссылка на родную планету персонажа.

 

Пример:

Получим персонаж с id=1. Массив "starships" отображает ссылки на космические корабли, с которыми связан персонаж с id=1.

 

Request:

GET /persons/1

Response:

Status: 200 OK{ "name": "Luke Skywalker", "height": "172", "mass": "77", "hair_color": "blond", "skin_color": "fair", "eye_color": "blue", "birth_year": "19BBY", "gender": "male", "homeworld": "http://swapi.co/api/planets/1/", "species": [ "http://swapi.co/api/species/1/" ], "vehicles": [ "http://swapi.co/api/vehicles/14/", "http://swapi.co/api/vehicles/30/" ], "starships": [ "http://swapi.co/api/starships/12/", "http://swapi.co/api/starships/22/" ], "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-20T21:17:56.891000Z"}

Массив "starships" содержит ссылки на объекты, по которым можно получить всю информацию о космических кораблях, которыми управлял персонаж.

 

8. REST архитектура предоставляет возможность получать коллекцию объектов, связанных с другим объектом, используя URL, указывающий на цепочку из объектов и ресурсов.

 

Пример:

Персонаж может быть пилотом космических кораблей. Чтобы получить все космические корабли, связанные с персонажем, мы используем URL /persons/1/starships

 

Request:

GET /persons/1/starships

Response:

Status: 200 OK{ "results": [ { "id": 12, "name": "Imperial shuttle", "model": "Lambda-class T-4a shuttle", "manufacturer": "Sienar Fleet Systems", "cost_in_credits": "240000", "length": "20", "max_atmosphering_speed": "850", "crew": "6", "passengers": "20", "cargo_capacity": "80000", "consumables": "2 months", "hyperdrive_rating": "1.0", "MGLT": "50", "starship_class": "Armed government transport", "pilots": [ "http://swapi.co/api/persons/1/", "http://swapi.co/api/persons/13/", "http://swapi.co/api/persons/14/" ], "created": "2014-12-15T13:04:47.235000Z", "edited": "2014-12-22T17:35:44.795405Z", "url": "http://swapi.co/api/starships/22/" }, { "id": 22, "name": "X-wing", "model": "T-65 X-wing", "manufacturer": "Incom Corporation", "cost_in_credits": "149999", "length": "12.5", "max_atmosphering_speed": "1050", "crew": "1", "passengers": "0", "cargo_capacity": "110", "consumables": "1 week", "hyperdrive_rating": "1.0", "MGLT": "100", "starship_class": "Starfighter", "pilots": [ "http://swapi.co/api/persons/1/", "http://swapi.co/api/persons/9/", "http://swapi.co/api/persons/18/", "http://swapi.co/api/persons/19/" ], "created": "2014-12-12T11:19:05.340000Z", "edited": "2014-12-22T17:35:44.491233Z", "url": "http://swapi.co/api/starships/12/" } ]}

Что тестировать:

- Ответ содержит все ссылки на связанные объекты.

- Представленные ссылки правильные и работают.

URL параметры

9. URL параметры могут использоваться для выборки каких-то конкретных объектов данного ресурса. Принцип работы очень схож с применением фильтров. Например, мы хотим получить всех персонажей Звездных Войн женского пола. В таком случае мы передадим параметр gender cо значением female.

 

Пример:

Выберем всех персонажей женского пола. Для этого передадим URL параметр gender=female

Request:

GET /persons?gender=female

Response:

Status: 200 OK{ "results": [ { "name": "Leia Organa", "height": "150", "mass": "49", "hair_color": "brown", "skin_color": "light", "eye_color": "brown", "birth_year": "19BBY", "gender": "female", "homeworld": "http://swapi.co/api/planets/2/", "species": [ "http://swapi.co/api/species/1/" ], "vehicles": [ "http://swapi.co/api/vehicles/30/" ], "starships": [], "created": "2014-12-10T15:20:09.791000Z", "edited": "2014-12-20T21:17:50.315000Z", "url": "http://swapi.co/api/persons/5/" }, { "name": "Beru Whitesun lars", "height": "165", "mass": "75", "hair_color": "brown", "skin_color": "light", "eye_color": "blue", "birth_year": "47BBY", "gender": "female", "homeworld": "http://swapi.co/api/planets/1/", "species": [ "http://swapi.co/api/species/1/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:53:41.121000Z", "edited": "2014-12-20T21:17:50.319000Z", "url": "http://swapi.co/api/persons/7/" } ]}

 

10. Query параметров может быть несколько и они могут применяться как по-отдельности, так и вместе.

 

Пример:

Выберем всех персонажей женского пола (gender=female) с планеты id=2 (homeworld=2) и все это на языке вуки (format=wookiee).

Request:

GET /persons?gender=female&homeworld=2&format=wookiee

Response:

Status: 200 OK{ "results": [ { "whrascwo": "Lwoahra Orcrrrawhra", "acwoahrracao": "150", "scracc": "49", "acraahrc_oaooanoorc": "rhrcooohwh", "corahwh_oaooanoorc": "anahrracao", "worowo_oaooanoorc": "rhrcooohwh", "rhahrcaoac_roworarc": "19BBY", "rrwowhwaworc": "wwwoscraanwo", "acooscwoohoorcanwa": "acaoaoak://cohraakah.oaoo/raakah/akanrawhwoaoc/2/", "cakwooaahwoc": [ "acaoaoak://cohraakah.oaoo/raakah/cakwooaahwoc/1/" ], "howoacahoaanwoc": [ "acaoaoak://cohraakah.oaoo/raakah/howoacahoaanwoc/30/" ], "caorarccacahakc": [], "oarcworaaowowa": "2014-12-10T15:20:09.791000Z", "wowaahaowowa": "2014-12-20T21:17:50.315000Z", "hurcan": "acaoaoak://cohraakah.oaoo/raakah/akwoooakanwo/5/" } ]}

 

11. Query параметры могут использовать также для указания конкретных полей, которые мы хотим получить в ответе.

 

Пример:

Получим всех персонажей, но в ответе нам нужнs только поля "id", "name" и "height". Для этого передадим URL параметр fields и перечислим нужные нам поля в качестве значения.

Request:

GET /persons?fields=id,name,height

Response:

Status: 200 OK{ "results": [ { "id": 1, "name": "Luke Skywalker", "height": "172" }, { "id": 2, "name": "C-3PO", "height": "167" }, { "id": 3, "name": "R2-D2", "height": "96" },..... ]}

 

12. Если отправить недопустимое значение параметра, веб-сервис должен вернуть ошибку.

 

Пример:

URL параметр gender имеет только 2 допустимых значения: male, female. Мы передадим недопустимое значение.

Request:

GET /persons?gender=1

Response:

Status: 400 Bad Request.Error: Invalid gender value.

 

Что тестировать:

- Допустимое значение query параметра.

- Различные комбинации query параметров и их значений.

- Недопустимое значение query параметра.

Права доступа

13. У пользователя, в контексте которого вы делаете запросы, может не быть прав на ту или иную информацию объекта. Тогда в ответе он получит только ту часть, к которой у него есть доступ.

 

Пример:

У космического корабля с id=22 есть полный набор параметров, например, name, model, velocity, manufacturer, cost_in_credits и т.д. У текущего пользователя есть доступ видеть только имя и модель космического корабля и он запрашивает корабль с id=22.

Request:

GET /starships/22

Response:

Status: 200 OK.{ "name": "Imperial shuttle", "model": "Lambda-class T-4a shuttle"}

 

Такой же набор параметров пользователь должен получить при запросе коллекции объектов.

 

Пример:

 

Request:

GET /starships

Response:

Status: 200 OK.{ "results": [ { "name": "TIE Advanced x1", "model": "Twin Ion Engine Advanced x1" }, { "name": "Executor", "model": "Executor-class star dreadnought" },.... ]}

 

 

14. У пользователя, в контексте которого вы делаете запросы, может не быть прав на доступ к объекту в целом. При запросе такого объекта веб-сервис возвращает ошибку.

 

Пример:

У пользователя нет доступа к космическому кораблю с id=22. Пользователь запрашивает космический корабль с id=22.

Request:

GET /starships/22

Response:

Status: 403 Forbidden.

 

Если пользователь запрашивает все космические корабли, тогда в полученной коллекции будет отсутствовать объект, к которому нет доступа (т.е. корабля с id=22).

 

Что тестировать:

- получить объект, к параметрам которого есть неполный доступ, и проверить полученные параметры;

- получить коллекцию, к параметрам объекта которой есть неполный доступ, и проверить полученные параметры;

- получить объект, к которому нет доступа;

- получить коллекцию, когда нет доступа ко всем объектам коллекции.

 

POST (PUT/PATCH)

Общая информация

15. POST метод позволяет создавать объекты в системе. PUT полностью заменяет существующие объекты новыми. PATCH обновляет объект той информацией, которая передана в запросе. Данные методы могут работать как с отдельными объектами, так и с коллекциями объектов.

 

Пример:

Создадим Звезду Смерти.

Request:

 

POST /starships{ "name": "Death Star", "model": "DS-1 Orbital Battle Station", "manufacturer": "Imperial Department of Military Research, Sienar Fleet Systems", "cost_in_credits": "1000000000000", "length": "120000", "max_atmosphering_speed": "n/a", "crew": "342953", "passengers": "843342", "cargo_capacity": "1000000000000", "consumables": "3 years", "hyperdrive_rating": "4.0", "MGLT": "10", "starship_class": "Deep Space Mobile Battlestation",}

Response:

Status: 201 CreatedHeaders: Location: http://swapi.co/api/starships/9

 

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

Например, если отправить тело без обязательных полей, веб-сервис должен вернуть ошибку 400 Bad Request и сказать, какие поля обязательны. Помните, что ошибки должны позволить определить причину ошибки.

Пример:

Для создания звездного корабля достаточно передать имя и модель. Пользователь отправляет запрос, указывая только его длину и максимальную скорость.

Request:

 

POST /starships{ "length": "120000", "max_atmosphering_speed": "300"}

Response:

Status: 400 Bad RequestError: "name", "model" required.

 

Пример:

Например, список допустимых значений для "starship_class" задается системой, а пользователь передает"starship_class": "Merchant Ship", которого нет в этом списке (считайте, что это аналог выпадающего списка)

Request:

 

POST /starships{ "name": "Millennium Falcon", "model": "YT-1300 light freighter", "manufacturer": "Corellian Engineering Corporation", "cost_in_credits": "100000", "length": "34.37", "max_atmosphering_speed": "1050", "crew": "4", "passengers": "6", "cargo_capacity": "100000", "consumables": "2 months", "hyperdrive_rating": "0.5", "MGLT": "75", "starship_class": "Merchant Ship" }

Response:

 

Status: 400 Bad RequestError: "starship_class" invalid value.

 

Что тестировать:

- создать/обновить объект и проверить, что переданные значения соответствуют новым значениям в базе данных (можно так же проверить на UI или послать GET запрос);

- создать новый объект без обязательных полей;

- обновить существующий объект, указав пустые значения в обязательные поля;

- создать/обновить объект, указав недопустимые значения (бизнес логика);

- создать/обновить объект, указав поля, которые недоступны пользователю (права доступа).

 

Связи

17. Выше мы говорили о связях объектов между собой в контексте GET метода. Для POST (PUT/PATCH) есть своя специфика, о которой стоит рассказать.

ЧТО НАСЧЕТ СВЯЗЕЙ В URL?

При создании объекта и наличии связи его с другим объектом, эта связь должна указываться в теле запроса. Например, у космического корабля может быть пилот. В таком случае в объекте "космический корабль" будет ссылка на объект "персонаж", который является пилотом.

 

Пример:

 

Например, мы создали Звезду Смерти, но не указали пилота. Можно сделать PATCH созданного объекта, чтобы обновить его, или сделать PUT, чтобы полностью заменить его новым переданным.

 

Request:

PUT /starships/9 { "name": "Death Star", "model": "DS-1 Orbital Battle Station", "manufacturer": "Imperial Department of Military Research, Sienar Fleet Systems", "cost_in_credits": "1000000000000", "length": "120000", "max_atmosphering_speed": "n/a", "crew": "342953", "passengers": "843342", "cargo_capacity": "1000000000000", "consumables": "3 years", "hyperdrive_rating": "4.0", "MGLT": "10", "starship_class": "Deep Space Mobile Battlestation" "pilots": [ "id": 4]}

Response:

Status: 201 CreatedHeaders: Location: http://swapi.co/api/starships/9

18. Если указать ссылку на несуществующий объект, веб-сервис должен вернуть ошибку, что объект не существует.

Пример:

Создадим корабль Y-wing, указав id пилота, которого не существует в системе.

Request:

POST /starships/9 { "name": "Y-wing", "model": "BTL Y-wing", "manufacturer": "Koensayr Manufacturing", "cost_in_credits": "134999", "length": "14", "max_atmosphering_speed": "1000km", "crew": "2", "passengers": "0", "cargo_capacity": "110", "consumables": "1 week", "hyperdrive_rating": "1.0", "MGLT": "80", "starship_class": "assault starfighter", "pilots": [ "id": 110110]}

Response:

Status: 404 Bad Request Error: Pilot not found

Что тестировать:

- Создать объект с указанием существующего связанного объекта.

- Создать объект с указанием НЕ существующего связанного объекта.

Права доступа

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

 

Пример:

 

Мы хотим сделать Obi-Wan Kenobi (id = 10) пилотом корабля (id = 13), который находится в секретной разработке и у текущего пользователя системы нет доступа.

 

Request:

PATCH /persons/10 {"starships": [ "id": 13]}

Response:

404 Bad Request Error: starship not found. or Error: starship is available for current user.

 

Пример:

 

Мы хотим сделать R2 D2 (id = 3) пилотом корабля (id = 12). Но этот персонаж не может быть пилотом корабля.

 

Request:

PATCH /persons/3 {"starships": [ "id": 12]}

Response:

404 Bad Request Error: The person cannot be a pilot of any starship.

 

Что тестировать:

 

- Создать объект с указанием существующего связанного объекта, но не доступного для текущего авторизированного пользователя.

- Создать объект с указанием существующего связанного объекта, но не разрешенного для создаваемого объекта.

 

Test tools

 

(Postman, VS Code (для работы с json/xml), json / xml online validators);

 

 

5. Resources:

 

1. https://en.wikipedia.org/wiki/Uniform_Resource_Locator

3. https://ru.wikipedia.org/wiki/REST

4. https://habrahabr.ru/post/38730/

5. https://habrahabr.ru/post/144011/

6. https://apigee.com/about/resources/ebooks/web-api-design

7. http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

8. http://secl.com.ua/article_rest_api_web.html

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...