Кращі практики проектування API в Laravel

Вкрадено звідси.

Ця публікація має аудіо-версію завдяки додатку Blogcast Мігеля П'єдрафіти.

Я не лише інженер DevOps, але ще з маленької дитини я починав з нуля землі, ще в часи, коли я був у 5-му класі. Відтоді я безперервно вдосконалював свій код і з'ясував, що люди прийняли якісь стандарти для чистішого коду, кращої візуалізації, а оскільки вони є стандартами, кожен міг краще зрозуміти, що пише кожен інший розробник у тій же базі коду.

Я завжди любив кодувати більше, ніж у бекенді, а не у фронтенді. Я намагався бути Full Stack, але це мені не підходило. Тому я знову відмовився від написання бекенду, особливо API. Цього разу я не буду говорити про стандарти кодування взагалі, але я розповім про те, які API працюють насправді та як їх легше розробити, від безпеки до порад, як зробити це краще.

По суті, API - це інтерфейс, який повертає дані у спеціальному форматі, який може зрозуміти будь-який додаток, будь то додаток для Android або веб-додаток.

JSON широко використовується, оскільки він є майже скрізь. Іншим варіантом є використання XML, але у мене виникли проблеми з деякими сторонніми API (особливо постачальниками платежів у моїй країні), які використовували XML через JSON, і розробка була загальним лаєм. Я рекомендую постійно розробляти API JSON, якщо хтось не вимагає API XML.

Розробляючи API, потрібно враховувати деякі речі в цьому конкретному порядку:

  • безпека - необхідне забезпечення за допомогою OAuth, ключа API або CORS. За бажанням вам слід використовувати дросель, щоб обмежити запити на ваш додаток.
  • заголовки - переконайтеся, що ваші програми надсилають потрібний тип вмісту. Заголовок типу вмісту - це трохи інформації, яка повідомляє клієнтові, який отримує дані: "ця річ, яку я вам надсилаю, це JSON" або "що тут XML. правильно проаналізувати », тому браузер або ваш клієнт знають, як правильно його розшифрувати.
  • стандарти кодування та іменування - це суто допоміжні дані. Переконайтеся, що ви послідовні у своїх відповідях. Дотримуйтесь лише одного виду імен та правильного форматування.

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

Безпека

Найбільша проблема, над якою слід подбати - це безпека. Забезпечити це легко, але якщо не робити це належним чином, ви можете отримати небажаний доступ. У Laravel ви можете скористатися паспортом Laravel - він належить до екосистеми Laravel, підтримує автентифікацію за допомогою цього ідентифікатора додатка - App Secret, що дозволяє отримати маркер доступу, щоб представити себе комусь або сервером, будь то бекенд або фронтенд. В основному, ви зробите запит з ідентифікатором додатка та секретом додатка до кінцевої точки OAuth, щоб отримати маркер, який може бути згенерований сервером (тобто, доступ до API з команди, яка працює щодня в cronjob) або користувач, який увійшов у ваш додаток.

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

Заголовки

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

Це так, як сказала вам мама: «іди купуй трохи молока в магазині, а купуй лише від молока марки X». Ви знаєте, що робити, але вам доведеться відбирати лише один вид молока. Це те саме, що запити: "я хочу отримати список користувачів, але дайте мені їх у JSON" або "я хочу отримати всіх користувачів, але надішліть мені шматки 20" (якщо ви вказуєте параметр GET ). Для цього є заголовок під назвою Accepts, який може бути application / json, якщо ви хочете відповідь як JSON. Це не обов'язково, але для деяких додатків, таких як AJAX, якщо він виявить цей заголовок, він автоматично розшифрує відповідь для клієнта, не виконуючи нічого подібного:

var data = JSON.parse (response.data);

Ще один заголовок, про який потрібно знати, - це Тип вмісту, який трохи заплутаний, але він протилежний Accepts: він повідомляє серверу, як поводитися з отриманим ним вмістом. Наприклад, якщо ви хочете надіслати дані RAW, наприклад, рядок JSON, ви можете встановити Content-Type для application / json, але якщо ви хочете отримувати вміст через змінну $ _POST, слід встановити його на x-www -форма-урленкодований. Це допоможе вам не лише аналізувати вміст безпосередньо через $ _POST, але його слід використовувати у формах HTML, оскільки він легко доступний. Якщо ви надсилаєте дані, наприклад, двійкові, через введення файлів, наприклад, переконайтеся, що ви надіслали вміст багаточастинні / форми-дані.

У Laravel це не буде проблемою, оскільки ви можете отримати доступ до даних безпосередньо.

Для застосування / json:

індекс функції (Запит $ запиту)
{
   $ var = $ request-> змінна;
}

Однак у застосуванні / json не можна побачити, використовуючи метод -> all () вміст JSON:

індекс функції (Запит $ запиту)
{
   $ data = $ request-> all (); // це порожній масив, навіть у нас є дані.
}

Якщо встановлено x-www-form-urlencoded або multipart / form-data, ви можете побачити всі змінні, використовуючи -> all ().

Відповідаючи на відповідь, у Laravel ви можете використовувати вбудовану відповідь JSON АБО ви можете опрацювати її краще та використовувати пакет, наприклад, Laravel Fractal або Laravel Responder. З мого власного досвіду, Laravel Responder зробив цю роботу краще, більш семантично. Дозвольте мені показати вам:

функція getUsers (Запит $ запиту)
{
   повернути відповідь () -> успіх (Користувач: усі ()) -> відповісти ();
}

Це поверне всіх користувачів зі статусом OK 200 та відформатованим як JSON. Класно, правда? Для помилок ви повинні зробити щось подібне, що дозволяє надіслати код та повідомлення:

функція getUsers (Запит $ запиту)
{
   $ users = Користувач :: all ();

   if ($ користувачів-> count () === 0) {
      return responder () -> помилка ('no_users', 'немає користувачів.') -> reply ();
   }
   повернути відповідь () -> успіх ($ користувачів) -> відповісти ();
}

Цей пакет підтримує набагато більше, тому перейдіть до документів, оскільки його можна легко інтегрувати з трансформерами та надісланими нестандартними даними.

Стандарти кодування

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

Використовуйте файл маршрутів / api.php для маршрутів API

Laravel постачається з окремими маршрутами / api.phpfile, який відкладається від звичайного файлу маршрутів / web.php, який використовується для веб-маршрутизації. Файл api.php створений для зберігання ваших маршрутів API. Він має вбудоване середнє програмне забезпечення (яке можна побачити в app / Http / Kernel.php, в змінній $ middlewareGroups, під api) та префікс / api, тому всі визначені маршрути вже доступні для / api

Скористайтеся назвами маршрутів

Що мені подобається робити, це встановити параметр для цілого API, щоб я мав доступ до маршрутів за їх іменем, з api. префікс.

Маршрут :: get ('/ users', 'API \ UserController @ getUsers') -> name ('get.users');

URL-адресу цього маршруту можна отримати за допомогою маршруту ("get.users"), але він може суперечити веб-сайту.

Route :: group (['as' => 'api.'], Function () {
   Маршрут :: get ('/ users', 'API \ UserController @ getUsers') -> name ('get.users');
});

Таким чином, ви матимете його на маршруті ('api.get.users').

Якщо ви використовуєте найменування маршруту, якщо ви користуєтеся тестами для запису, вам не потрібно буде всюди замінювати URL-адресу, якщо ви плануєте змінити розташування URL-адреси та зберегти назву маршруту.

Описові, але прості маршрути

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

Route :: group (['as' => 'api.'], Function () {
   Route :: group (['as' => 'account.', 'Prefix' => '/ account'], function () {
         Маршрут :: get ('/ users', 'API \ UserController @ getUsers') -> name ('get.users');
         Маршрут :: get ('/ user / {id}', 'API \ UserController @ getUser') -> name ('get.user');
         Route :: post ('/ user', 'API \ UserController @ createUser') -> name ('create.user');
         // тощо.
   });
});

Використовуйте :: get () для отримання даних, :: post () для створення, :: patch () або :: put () для редагування та :: delete () для видалення даних. Так, ви використовуєте ту саму кінцеву точку, але з різними видами запитів, ви зможете запустити інші дії.

Всередині вашого контролера ви повинні використовувати просте кодування та користуватися класами Request, як я пояснив далі в Pushing Laravel - кращі поради та хороші практики для Laravel 5.7

функція getUsers (Запит $ запиту)
{
   $ users = Користувач :: all ();
   повернути відповідь () -> успіх ($ користувачів) -> відповісти ();
}
функція getUser ($ id, Запит $ запиту)
{
   $ user = Користувач :: findOrFail ($ id);
   повернути відповідь () -> успіх ($ користувач) -> відповісти ();
}
функція createUser (CreateUserRequest $ запит)
{
    $ user = Користувач :: create ($ request-> all ());
    повернути відповідь () -> успіх ($ користувач) -> відповісти ();
}
// тощо.

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

Занадто важко зрозуміти? Доберись до мене!

Якщо у вас є додаткові запитання щодо Laravel, якщо вам потрібна допомога з будь-якою інформацією, що стосується DevOps або просто хочете сказати спасибі !, ви можете знайти мене на Twitter @rennokki!

Приєднуйтесь до нашої спільноти Slack та читайте наші щотижневі теми Faun ⬇

Якщо ця публікація була корисною, будь ласка, натисніть кнопку нижче кілька разів, щоб показати вашу підтримку автору! ⬇