Разработка 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 с документацией и поддержкой.







