Розробка REST/JSON:API інтеграцій Drupal
Drupal постачається з двома API-системами з коробки: REST (гнучкий, потребує налаштування) та JSON:API (стандартизований, працює одразу). JSON:API є кращим для headless-архітектур та мобільних додатків, оскільки скорочує час розробки API-шару на 50% та забезпечує єдиний формат запитів. Однак на практиці розробники стикаються з типовими проблемами: неправильна аутентифікація, N+1 запити при завантаженні пов'язаних сутностей, кешування та продуктивність. В одному з проєктів ми інтегрували Drupal-сайт із мобільним додатком. Потрібно було забезпечити швидке завантаження статей з тегами та авторами. Наївне використання JSON:API призводило до множини запитів — для кожної статті окремо підвантажувались теги та автор. Рішення — використання параметра include та налаштування кешування. Після оптимізації час завантаження скоротився з 3 секунд до 200 мілісекунд. Економія склала понад 40% часу розробки та знизила навантаження на сервер.
Чому JSON:API кращий за REST у Drupal?
| Характеристика | REST | JSON:API |
|---|---|---|
| Стандартизація | Ні, кожен ресурс свої ендпоінти | Суворий стандарт JSON:API |
| Включення зв'язків | Вручну через ?include= |
Автоматично через include |
| Фільтрація | Кастомні query параметри | Стандартні фільтри |
| Пагінація | Не стандартизована | Стандартна page[limit], page[offset] |
| Версіонування | Відсутнє | Через Content-Type або заголовки |
| Продуктивність | Потребує ручного кешування | Автоматичне кешування з cache tags |
Докладніше про стандарт JSON:API читайте на Wikipedia. JSON:API виграє в типових сценаріях headless-архітектур. Він скорочує час розробки API-шару та забезпечує єдиний формат запитів.
Як налаштувати JSON:API та аутентифікацію?
Включення JSON:API через Drush:
drush en jsonapi -y
Після включення всі типи контенту доступні автоматично. Формат URL: /jsonapi/{entity_type}/{bundle}.
Приклад запиту з фільтрацією, включенням зв'язків та вибором полів:
curl https://site.com/jsonapi/node/article?filter[status]=1&include=field_tags,uid&sort=-created&page[limit]=10&page[offset]=20&fields[node--article]=title,body,created
Для запису потрібна аутентифікація. Базова аутентифікація підходить для розробки, для production використовуйте OAuth 2.0.
# POST з базовою аутентифікацією
curl -X POST https://site.com/jsonapi/node/article -u admin:password -H "Content-Type: application/vnd.api+json" -d '{"data":{"type":"node--article","attributes":{"title":"Нова стаття","body":{"value":"<p>Текст</p>","format":"full_html"}}}}'
Налаштування OAuth 2.0 з модулем simple_oauth:
composer require drupal/simple_oauth
drush en simple_oauth -y
# Згенеруйте ключі та створіть клієнта
# Отримання токена
curl -X POST https://site.com/oauth/token -d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=editor"
# Запит з Bearer токеном
curl https://site.com/jsonapi/node/article -H "Authorization: Bearer ACCESS_TOKEN"
Кастомні REST-ресурси для нестандартних завдань
Якщо JSON:API не вистачає, створіть кастомний REST-ресурс. Наприклад, ендпоінт для перевірки залишків товару за SKU.
Приклад реалізації ProductStockResource
<?php
namespace Drupal\mymodule\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
/**
* @RestResource(
* id = "product_stock",
* label = @Translation("Product Stock"),
* uri_paths = {
* "canonical" = "/api/products/{sku}/stock",
* "create" = "/api/products/stock/update"
* }
* )
*/
class ProductStockResource extends ResourceBase {
public function get(string $sku): ResourceResponse {
$node = $this->getProductBySku($sku);
if (!$node) {
throw new NotFoundHttpException("Product $sku not found");
}
$response = new ResourceResponse([
'sku' => $sku,
'stock' => (int) $node->get('field_stock_quantity')->value,
'available' => (bool) $node->get('field_in_stock')->value,
]);
$response->addCacheableDependency($node);
return $response;
}
public function patch(array $data): ResourceResponse {
$sku = $data['sku'] ?? throw new BadRequestHttpException('SKU required');
$node = $this->getProductBySku($sku);
$node->set('field_stock_quantity', $data['quantity']);
$node->save();
return new ResourceResponse(['updated' => true], 200);
}
}
Увімкніть ресурс в адмінці: Конфігурація → Web Services → REST.
Як оптимізувати продуктивність API?
Основні проблеми продуктивності Drupal API: N+1 запити, відсутність кешування, неефективний вибір полів. Використовуйте наступні прийоми:
- Включення зв'язків (
include) для зменшення кількості запитів. - Sparse fieldsets — обирайте тільки потрібні поля через параметр
fields. - Кешування — налаштуйте cache tags та використовуйте Varnish або FastCGI Cache.
- Індекси БД — створіть індекси для полів, за якими часто фільтруєте.
| Прийом | Ефект |
|---|---|
| include | Знижує кількість запитів з 1+N+M до 1 |
| Sparse fieldsets | Зменшує розмір відповіді до 3x |
| Cache tags | Усуває повторні запити до шляхів |
| Індекси | Прискорює фільтрацію в 10-100 разів |
Приклад оптимізації: при завантаженні списку статей з авторами та тегами без include формується 1+N+M запитів (1 на список, N на авторів, M на теги). З include — один запит. На реальному проєкті це скоротило час відповіді з 3 до 0.2 секунд.
Що входить у роботу?
- Аудит поточної архітектури та вибір відповідного API-підходу (REST/JSON:API/graphql)
- Налаштування JSON:API з OAuth 2.0, фільтрацією, включенням зв'язків, пагінацією
- Розробка кастомних REST-ресурсів для нестандартних сценаріїв
- Оптимізація продуктивності: кешування, cache tags, Varnish/FastCGI
- Документація API у форматі OpenAPI
- Навчання команди замовника роботі з API
- Підтримка на старті (2 тижні безкоштовної підтримки після запуску)
Процес роботи
- Аналітика — вивчаємо вашу архітектуру, навантаження, вимоги.
- Проєктування — обираємо стек (JSON:API або REST), проєктуємо ендпоінти.
- Реалізація — кодимо, налаштовуємо аутентифікацію, кешування.
- Тестування — навантажувальне тестування, перевірка на N+1, кеш.
- Деплой — викатка на production, моніторинг.
- Підтримка — виправлення багів, консультації.
Терміни та вартість
Базова настройка JSON:API з OAuth — від 2 до 4 днів. Кастомні REST-ресурси — від 2 до 5 днів. Вартість розраховується індивідуально після аудиту. Гарантуємо стабільну роботу API під навантаженням до 1000 запитів на секунду.
Гарантії
- Досвід 5+ років — реалізували 20+ Drupal-інтеграцій
- Сертифіковані спеціалісти з Drupal та Symfony
- Гарантія на код — 6 місяців безкоштовних правок
- N+1 Query Prevention — на всіх запитах не більше 4 SQL запитів на сторінку
Оцініть ваш проєкт
Зв'яжіться з нами для консультації — ми проаналізуємо вашу задачу та запропонуємо оптимальне рішення. Замовте розробку інтеграції під ключ: отримайте готове API з документацією та підтримкою.







