Так чи потрібен rest для веб-додатків

Що таке REST?

Так чи потрібен rest для веб-додатків

Звичайне середньостатистичне веб-додаток обходиться двома типами запитів: GET і POST, для отримання і відповідно відправки даних. Але RESTful архітектура має на увазі використовувати весь спектр запитів: GET - отримати дані, POST - відправити нові дані, PUT - відправити відредаговані дані, DELETE - видалити дані. Є ще PATCH, який за своєю ідеї повторює PUT, відмінності лише в тому, що PUT передбачає замінити повністю запис, а PATCH тільки частково оновити дані. Що цікаво, думки про використання POST і PUT розходяться. Англомовні розробники вважають за краще використовувати саме PUT для додавання нових даних, а POST для редагування.

Використання REST на прикладі GML

Для початку нам потрібно визначитися з ресурсами, з якими може взаємодіяти користувач. На GML у мене вийшло: лінки (посилання на веб-ресурси), збірники (контейнери для лінків), користувачі і теги. Це чотири основних одиниці, з якими відбувається робота.

Позначимо кореневої домен як gml.link/

У нас виходять такі запити на отримання даних:

  • GET gml.link/links/ - отримати весь список лінків
  • GET gml.link/links/125 - отримати сто двадцять п'ятий лінк
  • GET gml.link/collections/ - отримати список всіх збірників
  • GET gml.link/collection/34 - отримати список лінків тридцять четвертого збірника
  • GET gml.link/tags/ - отримати список всіх тегів
  • GET gml.link/tags/animal - отримати список лінків з тегом 'animal' (для тегів в якості ідентифікатора виступає його назву, а не номер.)

Запити на додавання даних (в круглих дужках вказані дані передаються в тілі запиту)

  • POST gml.link/users/ (username: 'Alex', password: 'sdf7665 $ 6', email: '[email protected]') - додати нового користувача
  • POST gml.link/users/23 (username: 'Alex', password: 'sdf7665 $ 6', email: '[email protected]') - в даному випадку повернеться помилка, так як ми вказали в запиті ідентифікатор конкретного користувача
  • POST gml.link/collections/ (title: 'Нова колекція', 'type': 'private') - створить новий приватний збірник

Запити на редагування

  • PUT gml.link/collections/ (title: 'Змінена назва збірки') - поверне помилку, так як не вказано ідентифікатор збірки
  • PUT gml.link/collections/12 (title: 'Змінена назва збірки') - змінить назву у дванадцятого збірника
  • PUT gml.link/links/117 (title: 'Інша назва линка') - змінить назву у сто сімнадцятого линка

Запити на видалення

  • DELETE gml.link/collection/32 - видалить тридцять другому збірник
  • DELETE gml.link/links/43 - видалить сорок третій лінк

Так чи потрібен rest для веб-додатків

Зовсім трохи про технічну реалізації

(Увага, прочитавши цю частину, ваше життя може назавжди змінитися)

Так як ми не на Хабрахабр, тому технічну реалізацію я торкнуся умовно.

Весь процес обробки запиту ділиться на кілька етапів:

  1. Визначення ресурсу, до якого направлено запит (links, collections, users і tags, і id ресурсу)
  2. Визначення дії з типу запиту (отримання, додавання, редагування та видалення)
  3. Збір додаткових параметрів із запиту (для додавання \ редагування - це безпосередньо дані ресурсу, для отримання - це різні фільтри)

У чому переваги даного архітектурного підходу?

Застосувавши REST на своєму проекті, для себе я відзначив наступне:

Що далі? (в загальному)

Як я вже говорив, статті буду писати по мірі реалізації тієї чи іншої частини сервісу. На даний момент вже готова реєстрація / аутентифікація, повністю підтримана REST архітектура, реалізована "lazy load" подгрузка лінків, додавання / створення збірки.

-- Збереження стану сторінки через HTML5 History API (як бонус)
Знову ж таки, дуже опосередковане відношення до REST API

-- Ні плутанини з додатковою передачею параметрів в запитах і обробкою їх на сервері
Якраз і починається плутанина. Що передаємо через GET параметри, щось через POST в один і той же обробник.

-- Прозора логіка клієнтської частини програми
-- У разі потреби легко надати RESTful API для сторонніх додатків
А інші протоколи не пропонують цієї можливості?

У REST є багато невизначеностей і через це у кожного з'являються свої реалізації, які вони вважають еталонними.

Немає більш менш чіткої специфікації. Наприклад відповідь про помилку:
1. HTTP код
2. Завжди 200, інформація про помилку у відповіді
3. 1 і 2 варіант

Формат відповіді. Припустимо викликаємо метод отримання користувачів:
1. []
2. ]>
3. ]>
Хтось як любить, так і робить. Великий мінус якщо доводиться інтегруватися з декількома сервісами.

Веселощі починається, коли потреби виходять за рамки простого додавання, отримання списку, видалення (типовий CRUD), тобто виходимо за рамки /: collection /: id

Ось є якась сущьность, у який є властивості і методи. Як ці дії виконати?
1. POST /: collection /: id / on
2. Передавати "дія" в тілі POST
3. Чи взагалі використовувати, PUT, PATCH

Невелика проблема виникає, коли йде кросбраузерності запит (CORS) до нашого API. На кожен url (/: collection /: id) буде слати попередній OPTIONS запит, додаткові затримки.

Додали GET / PATCH / DELETE обробник /: collection /: id. І хочемо в браузерному додатку использвать JSONP, щоб позбутися від політик CORS. Доведеться додавати ще один обробник (3-в-1), для підтримки JSONP (він адже тільки GET).

Немає стандрат інструментів для опису сервісу, за типом WSDL. Точніше більш-менш широковживаних.

При типовому REST API, документація і параметри описуються вручну. Документація буде постійно відставати.