Настройка Strapi REST API / GraphQL API
Strapi автоматически генерирует REST API и GraphQL для всех content types. REST — доступен сразу, GraphQL — через отдельный плагин. Оба используют одну и ту же систему прав доступа.
REST API: структура запросов
Формат Strapi v4/v5 ответа:
{
"data": {
"id": 1,
"attributes": { "title": "Article", "slug": "article", "publishedAt": "..." }
},
"meta": {}
}
Фильтрация:
# Простой фильтр
GET /api/articles?filters[status][$eq]=published
# Несколько условий (AND)
GET /api/articles?filters[price][$gte]=100&filters[price][$lte]=500
# OR фильтр
GET /api/articles?filters[$or][0][title][$containsi]=react&filters[$or][1][content][$containsi]=react
# Операторы: $eq, $ne, $lt, $lte, $gt, $gte, $in, $notIn, $contains, $containsi, $startsWith, $endsWith, $null, $notNull
Populate (связи и компоненты):
# Заполнить все связи (1 уровень)
GET /api/articles?populate=*
# Конкретные поля
GET /api/articles?populate[author][fields][0]=name&populate[author][fields][1]=email
# Глубокий populate
GET /api/articles?populate[category][populate][icon]=true
# Динамические зоны
GET /api/pages?populate[sections][populate]=*
Пагинация, сортировка, поля:
# Пагинация по страницам
GET /api/articles?pagination[page]=2&pagination[pageSize]=10
# Пагинация по курсору (для бесконечного скролла)
GET /api/articles?pagination[start]=20&pagination[limit]=10
# Сортировка
GET /api/articles?sort[0]=publishedAt:desc&sort[1]=title:asc
# Только нужные поля
GET /api/articles?fields[0]=title&fields[1]=slug&fields[2]=excerpt
GraphQL
npm install @strapi/plugin-graphql
// config/plugins.js
module.exports = {
graphql: {
config: {
endpoint: '/graphql',
playgroundAlways: false, // false в production
defaultLimit: 10,
maxLimit: 100,
apolloServer: {
introspection: process.env.NODE_ENV !== 'production',
},
},
},
}
Playground: http://localhost:1337/graphql
Запросы:
# Список статей с категорией
query GetArticles($locale: I18NLocaleCode, $page: Int) {
articles(
locale: $locale
pagination: { page: $page, pageSize: 10 }
sort: "publishedAt:desc"
filters: { publishedAt: { notNull: true } }
) {
data {
id
attributes {
title
slug
excerpt
publishedAt
cover {
data {
attributes { url alternativeText formats }
}
}
category {
data {
attributes { name slug }
}
}
}
}
meta {
pagination { total pageCount }
}
}
}
# Одна статья
query GetArticle($slug: String!) {
articles(filters: { slug: { eq: $slug } }) {
data {
id
attributes {
title content publishedAt
author {
data { attributes { name bio avatar { data { attributes { url } } } } }
}
}
}
}
}
# Мутации (с аутентификацией)
mutation CreateComment($articleId: ID!, $text: String!) {
createComment(data: { article: $articleId, text: $text }) {
data {
id
attributes { text createdAt }
}
}
}
Кастомизация GraphQL
// src/index.ts — добавить кастомный резолвер
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension')
extensionService.use(({ nexus }) => ({
types: [
nexus.extendType({
type: 'Query',
definition(t) {
t.field('featuredArticles', {
type: 'ArticleEntityResponseCollection',
resolve: async (_root, _args, context) => {
const articles = await strapi.entityService.findMany(
'api::article.article',
{
filters: { featured: true },
populate: ['cover', 'category'],
sort: { publishedAt: 'desc' },
limit: 6,
}
)
return { data: articles }
},
})
},
}),
],
}))
},
}
Производительность API
// Ограничить maxPopulateDepth
// config/middlewares.js
{
name: 'strapi::populate-depth',
config: { maxDepth: 3 }
}
// Кэшировать тяжёлые запросы с Redis
const redis = new Redis(process.env.REDIS_URL)
const cachedFeatured = await redis.get('featured-articles')
if (cachedFeatured) return JSON.parse(cachedFeatured)
const articles = await strapi.entityService.findMany(...)
await redis.setex('featured-articles', 300, JSON.stringify(articles))
Сроки
Настройка GraphQL плагина, кастомных резолверов и оптимизация запросов — 2–3 дня.







