Что такое GraphQL?
GraphQL — язык запросов для API, разработанный Facebook (Meta) в 2012 году. В отличие от REST, где сервер определяет, какие данные возвращает каждый endpoint, GraphQL позволяет клиенту указать, какие именно поля ему нужны.
GraphQL vs. REST
| Характеристика | REST | GraphQL |
|---|---|---|
| Endpoint-ы | Несколько (/users, /posts) | Один (/graphql) |
| Получение данных | Сервер определяет структуру | Клиент указывает поля |
| Over-fetching | Часто | Исключён |
| Under-fetching | Требует нескольких запросов | Решено вложенными запросами |
| Версионирование | URL/заголовки | Эволюция схемы |
| Кеширование | Встроенное HTTP-кеширование | Сложнее |
Основные концепции
Queries — чтение данных (аналог GET):
query {
user(id: 42) {
name
email
posts { title createdAt }
}
}
Mutations — запись данных (аналог POST/PUT/DELETE):
mutation {
createUser(input: { name: "Alice", email: "alice@example.com" }) {
id
name
}
}
Subscriptions — обновления в реальном времени через WebSocket:
subscription {
newMessage(chatId: "123") {
content
sender { name }
}
}
Схема GraphQL
Схема определяет все доступные типы, queries и mutations:
type User {
id: ID!
name: String!
email: String!
role: Role!
posts: [Post!]!
}
enum Role { ADMIN USER VIEWER }
type Query {
user(id: ID!): User
users(limit: Int, offset: Int): [User!]!
}
type Mutation {
createUser(input: CreateUserInput!): User!
deleteUser(id: ID!): Boolean!
}
! означает, что поле не может быть null. Интроспекция для исследования API:
{
__schema {
types { name fields { name type { name } } }
}
}
Тестирование GraphQL-запросов
Тесты валидации запросов
| Тест | Ввод | Ожидание |
|---|---|---|
| Валидный запрос | { user(id: 42) { name } } | 200 с запрошенными полями |
| Несуществующее поле | { user(id: 42) { phone } } | Ошибка: поле не найдено |
| Отсутствует обязательный аргумент | { user { name } } | Ошибка: id обязателен |
| Неверный тип аргумента | { user(id: "abc") { name } } | Ошибка: несоответствие типа |
| Пустой запрос | {} | Синтаксическая ошибка |
Валидация ответа
- Возвращаются только запрошенные поля
- Non-nullable поля никогда не null
- Типы массивов возвращают массивы (даже пустые)
- Enum-значения соответствуют схеме
Тестирование Mutations
mutation {
createUser(input: { name: "Alice", email: "alice@example.com", role: USER }) {
id name email
}
}
Тестовые сценарии для Mutations
| Сценарий | Ожидание |
|---|---|
| Валидный ввод | Успех с созданным ресурсом |
| Отсутствует обязательное поле | Ошибка валидации |
| Невалидное значение enum | Ошибка: невалидный Role |
| Дублирование уникального поля | Ошибка конфликта |
| Неавторизованная mutation | Ошибка аутентификации |
Тестирование безопасности GraphQL
Атака глубиной запроса
{ user(id: 1) { posts { author { posts { author { posts { author { name } } } } } } } }
Тест: Отправляйте запросы с нарастающей глубиной. Проверьте, что сервер отклоняет превышающие лимит.
Атака сложностью запроса
{ users(limit: 10000) { posts(limit: 1000) { comments(limit: 1000) { author { name } } } } }
Тест: Проверьте применение лимитов сложности.
Отключение интроспекции в продакшне
{ __schema { types { name } } }
Тест: Проверьте, что запросы интроспекции не работают в продакшне.
Атака пакетными запросами
Тест: Проверьте лимиты пакетных запросов и применение rate limiting к пакетным операциям.
Инструменты тестирования GraphQL
| Инструмент | Назначение |
|---|---|
| GraphiQL / Playground | Интерактивный обозреватель |
| Postman | Поддержка GraphQL-запросов |
| Altair GraphQL Client | Полнофункциональный клиент |
| graphql-inspector | Diff и валидация схемы |
Практическое упражнение
- Исследуйте GraphQL API: Используйте Star Wars API GraphQL для отправки запросов и изучения схемы.
- Протестируйте mutations: С записываемым GraphQL API протестируйте CRUD-операции.
- Тестирование безопасности: Отправьте глубоко вложенные запросы и запросы интроспекции.
- Сравните REST vs GraphQL: Получите те же данные обоими подходами.
Ключевые выводы
- GraphQL позволяет клиентам запрашивать именно нужные данные
- Тестирование требует валидации queries, mutations, соответствия схеме и специфической безопасности
- Лимиты глубины, сложности и отключённая интроспекция — критические меры безопасности
- Проблема N+1 запросов — частая проблема производительности
- Интроспекция полезна для проектирования тестов, но должна быть отключена в продакшне