Що є рекомендованою схемою для планування кінцевих точок REST для передбачуваних змін


25

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

Основна проблема, що стосується цієї статті, полягає в тому, яку модель слід дотримуватися для всіх визначених кінцевих точок для даного товару / компанії.

Базова схема

Враховуючи шаблон базової URL-адреси, https://rest.product.com/я припустив, що всі сервіси проживають /apiразом із /authіншими кінцевими точками на основі не відпочинку /doc. Тому я можу встановити базові кінцеві точки таким чином:

https://rest.product.com/api/...
https://rest.product.com/auth/login
https://rest.product.com/auth/logout
https://rest.product.com/doc/...

Кінцеві точки обслуговування

Тепер про самі кінцеві точки. Заклопотаність POST, GET, DELETEне є основною метою даної статті і є турботою про самих цих діях.

Кінцеві точки можна розділити на простори імен та дії. Кожна дія повинна також представляти себе таким чином, щоб підтримувати фундаментальні зміни типу повернення або необхідних параметрів.

Беручи гіпотетичну службу чату, де зареєстровані користувачі можуть надсилати повідомлення, у нас можуть бути такі кінцеві точки:

https://rest.product.com/api/messages/list/{user}
https://rest.product.com/api/messages/send

Тепер додамо підтримку версій для майбутніх змін API, які можуть бути порушеними. Ми могли або додати версію підпису після, /api/або після /messages/. З огляду на sendкінцеву точку, ми можемо мати наступне для v1.

https://rest.product.com/api/v1/messages/send
https://rest.product.com/api/messages/v1/send

Тож перше моє запитання - що рекомендується для ідентифікатора версії?

Керування кодом контролера

Отже, тепер ми встановили, що нам потрібно підтримувати попередні версії, щоб таким чином якось обробити код для кожної з нових версій, яка може з часом застаріти. Припускаючи, що ми пишемо кінцеві точки на Java, ми могли б керувати цим за допомогою пакетів.

package com.product.messages.v1;
public interface MessageController {
    void send();
    Message[] list();
}

Це має перевагу в тому, що весь код був розділений через простори імен, де будь-яка зміна перерви означатиме, що нова копія кінцевих точок служби. Шкода цього полягає в тому, що весь код потрібно скопіювати, а виправлення помилок, які бажають застосувати до нових та попередніх версій, потрібно застосувати / протестувати до кожної копії.

Інший підхід полягає у створенні обробників для кожної кінцевої точки.

package com.product.messages;
public class MessageServiceImpl {
    public void send(String version) {
        getMessageSender(version).send();
    }
    // Assume we have a List of senders in order of newest to oldest.
    private MessageSender getMessageSender(String version) {
        for (MessageSender s : senders) {
            if (s.supportsVersion(version)) {
                return s;
            }
        }
    }
}

Це тепер виокремлює версію до кожної кінцевої точки і робить виправлення помилок зворотного порту сумісним, оскільки в більшості випадків потрібно застосовувати лише один раз, але це означає, що нам потрібно зробити трохи більше роботи до кожної окремої кінцевої точки, щоб підтримати це.

Отже, є моє друге питання "Який найкращий спосіб створити код служби REST для підтримки попередніх версій".

Відповіді:


13

Отже, є моє друге питання "Який найкращий спосіб створити код служби REST для підтримки попередніх версій".

Дуже ретельно розроблений та ортогональний API, ймовірно, ніколи не потрібно буде змінювати назад несумісними способами, тому справді найкращим способом є не мати майбутніх версій.

Звичайно, ви, мабуть, не дійсно отримаєте це з першої спроби; Так:

  • Версія свого API, як ви плануєте (і це API, який розроблений, а не окремі методи всередині), і шуміть з цього приводу. Переконайтесь, що ваші партнери знають, що API може змінюватися, і що їхні програми повинні перевірити, чи не використовується вони остання версія; і порадити користувачам оновити, коли буде доступний новий. Підтримка двох старих версій є важкою, підтримка п'яти неможлива.
  • Протистояти прагненню оновлювати версію API з кожним "випуском". Нові функції, як правило, можуть бути переведені в поточну версію, не порушуючи існуючих клієнтів; вони нові функції. Останнє, що ви хочете, - це те, щоб клієнти ігнорували номер версії, оскільки це все одно сумісність назад. Оновіть версію API лише тоді, коли ви абсолютно не можете рухатися вперед, не порушуючи існуючий API.
  • Коли настає час створити нову версію, найпершим клієнтом має стати реалізація попередньої версії, сумісну назад. "API підтримки" повинен бути реалізований у поточному API. Таким чином, ви не на гачку, щоб витримати кілька повних реалізацій; лише поточна версія та кілька «оболонок» для старих версій. Запуск тесту регресії для тепер уже застарелого API для зворотного придатного клієнта - це хороший спосіб перевірити як новий API, так і рівень сумісності.

3

Перший варіант дизайну URI краще висловлює думку про те, що ви оновлюєте весь API. Друге можна трактувати як версію самих повідомлень. Тож це краще ІМО:

rest.product.com/api/v1/messages/send

Для клієнтської бібліотеки я думаю, що використання двох повних реалізацій в окремих пакетах Java є більш чистим, простішим у використанні та простішим у обслуговуванні.

При цьому, існують кращі методи для розробки API, ніж версії. Я погоджуюсь з вами, що ви повинні бути готові до цього, але я вважаю, що версію як крайній метод слід використовувати обережно і щадно. Клієнти відносно великі зусилля для модернізації. Нещодавно я виклав кілька таких думок у публікації в блозі:

http://theamiableapi.com/2011/10/18/api-design-best-practice-plan-for-evolution/

Що стосується версії API REST, то ця публікація Марка Ноттінгема стане вам корисною:

http://www.mnot.net/blog/2011/10/25/web_api_versioning_smackdown


3

Іншим підходом до обробки версій API є використання версії в заголовках HTTP. Подібно до

POST /messages/list/{user} HTTP/1.1
Host: http://rest.service.com
Content-Type: application/json
API-Version: 1.0      <----- like here
Cache-Control: no-cache

Ви можете проаналізувати заголовок та обробити його відповідним чином у бекенді.

При такому підході клієнтам не потрібно змінювати URL-адресу, а лише заголовок. А також це робить кінцеві точки REST завжди чистішими.

Якщо хтось із клієнтів не надіслав заголовок версії, ви надсилаєте запит 400 - Неправильний або ви можете обробити його з сумісною назад версією вашого API.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.