Приницы 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=d1f673d4df7e6a71822a5bdc89a702c581479232563Response: 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
Приницы 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/133123Response: Status: 404 Not Found Error: Specified object is not found.
4. Если запрашиваемый объект был удален, веб-сервис должен вернуть ошибку, например 301 Moved Permanently или 404 Not Found (зависит от конкретной реализации).
Пример: Персонаж с id = 967 был удален. Отправляем запрос на получение персонажа id = 967.
Request: GET /persons/967Response: Status: 301 Moved Permanently Error: Requested object has been removed.
5. Если у пользователя нет доступа к определенному объекту из-за ограниченных прав доступа, веб-сервис должен вернуть ошибку.
Пример: У пользователя нет доступа к персонаж с id = 364. Отправляем запрос на получение персонажа id = 364.
Request: GET /persons/364Response: 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/1Response: 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/starshipsResponse: 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=femaleResponse: 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=wookieeResponse: 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,heightResponse: 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=1Response: 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/22Response: Status: 200 OK.{ "name": "Imperial shuttle", "model": "Lambda-class T-4a shuttle"}
Такой же набор параметров пользователь должен получить при запросе коллекции объектов.
Пример:
Request: GET /starshipsResponse: 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/22Response: 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/918. Если указать ссылку на несуществующий объект, веб-сервис должен вернуть ошибку, что объект не существует. Пример: Создадим корабль 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 Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|