REST API
REST (скор. Англ. Representational State Transfer, «передача репрезентативного стану») — підхід до архітектури мережевих протоколів, які забезпечують доступ до інформаційних ресурсів. Був описаний і популяризований 2000 року Роєм Філдінгом, одним із творців протоколу HTTP. В основі REST закладено принципи функціонування Всесвітньої павутини і, зокрема, можливості HTTP. Філдінг розробив REST паралельно з HTTP 1.1 базуючись на попередньому протоколі HTTP 1.0.
Дані повинні передаватися у вигляді невеликої кількості стандартних форматів (наприклад, HTML, XML, JSON). Будь-який REST протокол (HTTP в тому числі) повинен підтримувати кешування, не повинен залежати від мережевого прошарку, не повинен зберігати інформації про стан між парами «запит-відповідь». Стверджується, що такий підхід забезпечує масштабовність системи і дозволяє їй еволюціонувати з новими вимогами. Антиподом REST є підхід, заснований на виклику віддалених процедур (Remote Procedure Call, RPC). Підхід RPC дозволяє використовувати невелику кількість мережевих ресурсів з великою кількістю методів і складним протоколом. При підході REST кількість методів і складність протоколу суворо обмежені, що призводить до того, що кількість окремих ресурсів має бути великою.
REST — це архітектурний стиль для розподілених гіпертекстових систем.
Зміст
Архітектурні обмеження
REST, як і кожен архітектурний стиль відповідає ряду архітектурних обмежень (англ. architectural constraints). Це гібридний стиль який успадковує обмеження з інших архітектурних стилів.
Клієнт-сервер
Перша архітектура від якої він успадковує обмеження — це клієнт-серверна архітектура. Її обмеження вимагає розділення відповідальності між компонентами, які займаються зберіганням та оновленням даних (сервером), і тими компонентами, які займаються відображенням даних на інтерфейсі користувача та реагування на дії з цим інтерфейсом (клієнтом). Таке розділення дозволяє компонентам еволюціонувати незалежно.
Відсутність стану
Наступним обмеженням є те, що взаємодії між сервером та клієнтом не мають стану, тобто кожен запит містить всю необхідну інформацію для його обробки, і не покладається на те, що сервер знає щось з попереднього запиту.
Відсутність стану не означає що стану немає. Відсутність стану означає, що сервер не знає про стан клієнта. Коли клієнт, наприклад, запитує головну сторінку сайту, сервер відповідає на запитання і забуває про клієнта. Клієнт може залишити сторінку відкритою протягом кількох років, перш ніж натиснути посилання, і тоді сервер відповість на інший запит. Тим часом сервер може відповідати на запити інших клієнтів, або нічого не робити — для клієнта це не має значення.
Таким чином, наприклад дані про стан сесії (користувача, який автентифікувався) зберігаються на клієнті, і передаються з кожним запитом. Це покращує масштабовність, бо сервер після закінчення обробки запиту може звільнити всі ресурси, задіяні для цієї операції, без жодного ризику втратити цінну інформацію. Також спрощується моніторинг і зневадження, бо для того аби розібратись, що відбувається в певному запиті, досить подивитись лише на той один запит. Збільшується надійність, бо помилка в одному запиті не зачіпає інші.
Мінусом цього обмеження є те, що знижується продуктивність через те, що в кожен запит тепер доводиться додавати дані сесії з клієнта. Також збереження стану на різних клієнтах важче підтримувати, бо реалізації клієнтів можуть відрізнятись, тоді як середовище сервера повністю під контролем розробника.
Кешування
Додатковим обмеженням стилю REST є те, що системи, написані в цьому стилі, повинні підтримувати кешування, тобто дані, які передаються сервером, повинні містити інформацію про те, чи можна їх кешувати, і якщо можна, то як довго. Це дозволяє збільшувати продуктивність, уникаючи зайвих запитів, але також зменшує надійність системи, через те, що дані в кеші можуть бути застарілими.
Рання архітектура веб, створена Тімом Бернерсом-Лі відповідала цим трьом обмеженням — клієнт-сервер без стану з підтримкою кешування. Проте стиль REST додає ще додаткові обмеження.
Однорідний інтерфейс
Всі компоненти в архітектурі REST підтримують однорідний інтерфейс. Це зменшує зв'язність між компонентами і сервісами які вони надають і дозволяє нескладно змінювати компоненти при потребі. Це досягається кількома точнішими обмеженнями:
- ідентифікація ресурсів
- маніпуляція ресурсами через представлення
- самоописові повідомлення
- гіпермедіа як рушій стану застосунку
Шари абстракції
Наступним обмеженням для REST є поділ на шари абстракції. Кожен компонент потрапляє в якийсь шар, і спілкується лише з компонентами в шарі під ним або в шарі над ним. Обмежнення знання системи одним шаром зменшує складність компонентів.
Запитування коду
Останнім архітектурним обмеженням в REST є те що клієнти повинні дозволяти розширювати свою функціональність дозволяючи завантаження додаткового коду в формі аплетів чи скриптів. Це спрощує клієнти, дозволяючи не реалізовувати всі необхідні функції попередньо. Щоправда це необов'язкове обмеження, і якщо воно не дає переваг для конкретного застосування, то його не обов'язково реалізовувати. Наприклад, дозвіл завантаження стороннього коду може бути не бажаним з точки зору безпеки.
Архітектурні елементи
Елементи даних
Компоненти REST системи спілкуються, передаючи один одному представлення ресурсу в форматі, що обирається з оновлюваного набору стандартних форматів даних. Формат обирається динамічно відповідно до бажань компонента-клієнта і можливостей сервера. Чи представлення має той самий формат, що й сам ресурс, чи є результатом якогось перетворення — це деталь реалізації, яка ховається за інтерфейсом.
Ресурс
Ресурс — це ключовий елемент даних в REST. Ресурсом може бути що завгодно що можна назвати: якийсь документ (наприклад зображення), динамічне значення (наприклад погода у Львові), щось з реального світу (наприклад працівник компанії). Але якщо точніше, то ресур— це функція приналежності що відображає моменти в часі на множину однотипних сутностей чи значень. Множина може бути порожньою, тобто REST дозволяє посилання на якийсь об'єкт якого ще не існує.
Ресурс може бути динамічним, наприклад ресурс «стаття про REST у вікіпедії» час від часу оновлює свій вміст, а може бути статичним, і після появи ніколи не змінювати свого значення, наприклад «перша версія статті про REST у вікіпедії». У REST такі два ресурси вважаються різними, хоча в певний момент часу вони можуть вказувати на одну й ту ж сутність. Єдине що важливо — семантика відображення імені ресурсу на його вміст.
Ідентифікатор ресурсу
Для того, щоб посилатись на ресурси, використовуються ідентифікатори ресурсів. Компонент, який надав ресурсу ідентифікатор і дозволяє звертатись до нього за цим ідентифікатором, відповідає за збереження функції приналежності незмінною. Якість ідентифікатора залежить від якості компонента, який цей ідентифікатор надає, тому деякі ідентифікатори стають «мертвими посиланнями», коли інформацію переміщують або знищують. Приклади ідентифікаторів ресурсу: URL, URN.
Представлення
Представлення (англ. Representation) — це послідовність байтів та метадані представлення, для того щоб описати ці байти. Часто, представлення називають документом, файлом, повідомленням HTTP тощо.
Приклади представлення: фотографія JPEG, документ HTML. Приклад метаданих представлення — тип медіа, час останньої зміни. Метадані також можуть бути не лише в представлення ресурсу, а й в самого ресурсу. Прикладами метаданих ресурсу є посилання на джерело, <link rel="alternates"... />, заголовок HTTP vary
Контрольні дані в представленні описують ціль повідомлення між компонентами, наприклад прохання про дію (створити, змінити видалити ресурс), або значення відповіді (наприклад поточний стан ресурсу, чи значення якогось іншого ресурсу, наприклад опис помилки).
Також, контрольні дані, включені в запити чи відповіді, можуть керувати поведінкою кеша. Прикладом таких контрольних даних можуть бути заголовки HTTP if-modified-since та cache-control.
Формат даних представлення називають типом медіа (англ. media type). Одні типи медіа краще підходять для автоматичної обробки, інші — для того щоб бути показаними користувачу. Композитні типи медіа можуть використовуватись для того, аби поєднати кілька видів представлення в одному. Від формату даних дуже залежить латентність застосунку, яку сприймає користувач. Наприклад, браузер може почати показувати сторінку ще до того, як завантажиться ввесь HTML, це збільшує видиму швидкість роботи.
Конектори
Конектори надають інтерфейс для комунікації компонентів, приховуючи реалізації ресурсів та механізм комунікації. Конектори подібні на віддалений виклик процедур, але з певними нюансами щодо передачі параметрів та результату виклику. Параметри складаються з ідентифікатора ресурсу, контрольних даних та необов'язково, представлення. Результат — з контрольних даних відповіді і представлення. Можна абстрагуватись і вважати такий виклик синхронним, але насправді передача даних відбувається потоково, тому обробку даних можна починати ще до того як отримані всі дані, таким чином зменшуючи латентність.
Двома найважливішими типами конекторів є клієнт і сервер. Відмінністю між ними є те що клієнт ініціює запит, в той час як сервер очікує запитів і відповідає на них даючи доступ до своїх сервісів. Компонент може містити одночасно як серверні так і клієнтські конектори. Додатковим типом конектора є кеш. Кеш може бути як клієнтським, для уникнення зайвих запитів, так і серверним — для уникнення зайвого обчислення відповіді на запит. Тому що інтерфейс однорідний, кеш легко може дізнатись чи запит можна кешувати. За замовчуванням, відповідь на запит отримання ресурсу можна кешувати, а запити зміни ресурсу — ні. Проте ці замовчування можна перевантажити контрольними даними.
Резолвер (англ. resolver) — це ще один тип конектора, який перетворює ідентифікатори ресурсів в інформацію про мережеві адреси необхідну компонентам щоб отримати цей ресурс. Наприклад в URI міститься доменне ім'я, і для доступу до відповідного домена, потрібно дізнатись в DNS-сервера адресу. Тому в цьому випадку система DNS грає роль резолвера. Використання одного чи кількох резолверів може збільшити життєздатність ідентифікатора ресурсу, через те що він не вказує напряму на фізичне розташування ресурсу яке може змінитись. Останньою формою конектора є тунель, який просто проводить запити через межу системи, наприклад, через фаєрвол. Причиною, через яку тунелі включено до архітектури REST, а не закрито абстракцією мережі, є те, що певні компоненти можуть перетворюватись на тунелі за запитом. Наприклад тунель HTTP активується при отриманні запиту з методом CONNECT.