Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Что такое REST
REST (Representational State Transfer) — это архитектурный стиль для построения веб-API. Это одно из самых важных понятий для QA Engineer, потому что большую часть времени я тестирую REST API. Расскажу подробно.
Определение
REST — это набор принципов (constraints) для организации communication между client-ом и server-ом через HTTP.
Создатель: Roy Fielding (2000)
Главная идея: Использовать стандартные HTTP методы (GET, POST, PUT, DELETE) для выполнения операций над ресурсами.
Ключевые концепции REST
1. Resources (Ресурсы)
Определение: Всё в REST — это ресурсы. Пользователь — ресурс, заказ — ресурс, продукт — ресурс.
Примеры:
/users → collection of users
/users/123 → specific user with ID 123
/orders → collection of orders
/orders/456 → specific order
/products → collection of products
Правило: Используй существительные (nouns), НЕ глаголы.
❌ Плохо: /getUser, /createOrder, /deleteProduct
✓ Хорошо: /users, /orders, /products
2. HTTP Methods (Методы)
REST использует стандартные HTTP методы для операций:
| Метод | Операция | Пример | Idempotent |
|---|---|---|---|
| GET | Получить | GET /users/123 | Да |
| POST | Создать | POST /users | Нет |
| PUT | Заменить целиком | PUT /users/123 | Да |
| PATCH | Частичное обновление | PATCH /users/123 | Нет (иногда да) |
| DELETE | Удалить | DELETE /users/123 | Да |
Пример — операции с пользователем:
Создать пользователя:
POST /users
Body: {"name": "John", "email": "john@example.com"}
Response: 201 Created
Получить пользователя:
GET /users/123
Response: 200 OK {"id": 123, "name": "John", "email": "john@example.com"}
Обновить пользователя:
PUT /users/123
Body: {"name": "John Updated", "email": "john@example.com"}
Response: 200 OK
Частичное обновление:
PATCH /users/123
Body: {"email": "john_new@example.com"}
Response: 200 OK
Удалить пользователя:
DELETE /users/123
Response: 204 No Content
3. Status Codes (Коды ответа)
REST API использует HTTP status codes для информирования client-а о результате:
2xx — Success:
- 200 OK — успешный request, вернули данные
- 201 Created — ресурс создан
- 204 No Content — успешно, но нет данных в ответе (например, DELETE)
3xx — Redirect:
- 301 Moved Permanently — ресурс moved
- 304 Not Modified — данные не изменились (кеширование)
4xx — Client Error:
- 400 Bad Request — неправильный формат
- 401 Unauthorized — нужна авторизация
- 403 Forbidden — access denied
- 404 Not Found — ресурс не найден
5xx — Server Error:
- 500 Internal Server Error — ошибка сервера
- 503 Service Unavailable — сервис недоступен
При тестировании я проверяю:
✓ GET существующего ресурса → 200
✓ GET несуществующего → 404
✓ POST с invalid данными → 400
✓ POST без авторизации → 401 или 403
✓ DELETE вернул 204 (no content)
✓ Сервер error вернул 500 (не 200)
4. Request/Response Format
Обычно REST использует JSON для обмена данными:
POST /users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer token123
{
"name": "John Doe",
"email": "john@example.com",
"age": 30
}
HTTP/1.1 201 Created
Content-Type: application/json
{
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"age": 30,
"created_at": "2025-03-15T10:30:00Z"
}
6 Constraints REST (по Roy Fielding)
1. Client-Server Architecture
Идея: Client и Server разделены. Client НЕ знает, как внутри Server работает.
Для QA: Я могу тестировать API, не смотря на Server code.
2. Statelessness
Идея: Каждый request содержит всю информацию, необходимую для его обработки. Server НЕ хранит state о client-е между requests.
Пример — Stateless:
Request 1: GET /users/123
Authorization: Bearer token123
Request 2: GET /users/456
Authorization: Bearer token123
(Сервер НЕ помнит, что мы делали в Request 1)
Почему это хорошо?
- Масштабируемость — Request может пойти на любой Server
- Надёжность — No session corruption
- Кеширование — Легче кешировать
При тестировании я проверяю:
✓ Каждый request self-contained?
✓ Не зависит ли результат от порядка requests?
✓ Можно ли запросы повторять в любом порядке?
3. Uniform Interface
Идея: Единообразный interface между client-ом и server-ом.
Включает:
- Resource Identification — ресурсы identified в requests (via URL)
- Resource Manipulation — используем representations (JSON) и standard HTTP methods
- Self-Descriptive Messages — response content-type, status code, headers объясняют себя
- HATEOAS (опционально) — response содержит links для next actions
Пример:
GET /users/123 Response:
{
"id": 123,
"name": "John",
"_links": {
"self": {"href": "/users/123"},
"all_users": {"href": "/users"},
"update": {"href": "/users/123", "method": "PUT"},
"delete": {"href": "/users/123", "method": "DELETE"}
}
}
4. Cacheability
Идея: Response должны быть cacheable (если это применимо).
HTTP caching headers:
Cache-Control: max-age=3600 // Cache на 1 час
ETag: "abc123" // Version identifier
Last-Modified: 2025-03-15T10:00:00Z
При тестировании:
✓ GET /users возвращает Cache-Control header?
✓ Повторный GET быстрее (from cache)?
✓ После POST/PUT/DELETE, cache инвалидируется?
5. Layered System
Идея: API может быть структурирована в layers (Gateway, Server, Database).
Client НЕ знает, сколько layers между ним и данными.
Пример:
Client
↓ (HTTP)
API Gateway (routing, throttling)
↓
Load Balancer
↓
Server 1, 2, 3 (horizontal scaling)
↓
Database (реplicated, cached)
6. Code on Demand (опционально)
Идея: Server может отправить executable code (JavaScript) client-у.
Это опционально и редко используется.
REST vs SOAP vs GraphQL
| Аспект | REST | SOAP | GraphQL |
|---|---|---|---|
| Сложность | Simple | Complex | Medium |
| Learning curve | Easy | Hard | Medium |
| Use case | Most cases | Legacy, critical | Complex queries |
| Overfetching | Да (можешь получить лишние данные) | Нет | Нет |
| Underfetching | Да (нужны multiple requests) | Нет | Нет |
| Caching | Хороший | Сложный | Сложный |
Мой опыт: REST наиболее популярен и легко тестировать. SOAP использую редко (legacy systems). GraphQL интересен, но more complex для тестирования.
RESTful API Best Practices
1. Versioning
/api/v1/users → Version 1
/api/v2/users → Version 2 (breaking changes)
2. Pagination
GET /users?page=1&limit=10
Response:
{
"data": [...],
"pagination": {
"page": 1,
"limit": 10,
"total": 500,
"next": "/users?page=2"
}
}
3. Filtering & Sorting
GET /users?status=active&sort=name&order=asc
4. Error Handling
GET /users/999 (not found)
Response: 404 Not Found
{
"error": {
"code": "USER_NOT_FOUND",
"message": "User with ID 999 does not exist",
"details": {...}
}
}
Как я тестирую REST API
Tools
Manual testing:
- Postman
- Insomnia
- Thunder Client
- curl
Automated testing:
- pytest + requests (Python)
- RestAssured (Java)
- Supertest (Node.js)
Test Cases
class TestUserAPI:
"""Test REST API for /users endpoint"""
def test_get_user_success(self):
"""GET /users/123 returns 200 with user data"""
response = requests.get("https://api.example.com/users/123")
assert response.status_code == 200
assert response.json()["id"] == 123
assert "name" in response.json()
def test_get_user_not_found(self):
"""GET /users/999 returns 404 when user doesn't exist"""
response = requests.get("https://api.example.com/users/999")
assert response.status_code == 404
def test_create_user(self):
"""POST /users creates new user and returns 201"""
payload = {"name": "John", "email": "john@example.com"}
response = requests.post("https://api.example.com/users", json=payload)
assert response.status_code == 201
assert response.json()["id"] > 0
def test_create_user_invalid_email(self):
"""POST /users with invalid email returns 400"""
payload = {"name": "John", "email": "invalid-email"}
response = requests.post("https://api.example.com/users", json=payload)
assert response.status_code == 400
def test_update_user(self):
"""PUT /users/123 updates user and returns 200"""
payload = {"name": "Jane"}
response = requests.put("https://api.example.com/users/123", json=payload)
assert response.status_code == 200
def test_delete_user(self):
"""DELETE /users/123 removes user and returns 204"""
response = requests.delete("https://api.example.com/users/123")
assert response.status_code == 204
def test_list_users_pagination(self):
"""GET /users?page=1&limit=10 returns paginated list"""
response = requests.get("https://api.example.com/users?page=1&limit=10")
assert response.status_code == 200
assert "pagination" in response.json()
assert len(response.json()["data"]) <= 10
Выводы
REST — это:
- Архитектурный стиль для веб-API (НЕ стандарт, а рекомендация)
- Использует HTTP методы — GET, POST, PUT, DELETE
- Работает с ресурсами — /users, /orders, /products
- Stateless — каждый request независим
- Использует HTTP status codes — 200, 404, 500 и т.д.
- Easy to test — стандартные HTTP tools
Для QA: REST API легче тестировать, чем другие архитектуры, потому что API predictable, используют standard HTTP, и легко воспроизводить requests.