← Назад к вопросам

Вокруг чего работает REST API

1.3 Junior🔥 191 комментариев
#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Вокруг чего работает REST API

Основной принцип

REST API работает вокруг РЕСУРСОВ — сущностей, которыми можно манипулировать через стандартные HTTP операции.

Вместо глаголов (действий):
/api/createUser
/api/deleteUser
/api/updateUser

REST использует существительные (ресурсы) + HTTP методы:
/api/users (GET, POST, PUT, DELETE)

Четыре ключевых концепции REST

1. Ресурсы (Resources)

# Ресурсы — это сущности в системе

# Users — ресурс
GET /api/users          # Получить всех пользователей
GET /api/users/42       # Получить пользователя с ID 42
POST /api/users         # Создать нового пользователя
PUT /api/users/42       # Обновить пользователя 42
DELETE /api/users/42    # Удалить пользователя 42

# Posts — другой ресурс
GET /api/posts          # Все посты
POST /api/posts         # Создать пост

# Comments — подресурс
GET /api/posts/1/comments   # Комментарии поста 1
POST /api/posts/1/comments  # Добавить комментарий к посту 1

2. HTTP методы (Verbs)

GET     — читать данные (безопасно, идемпотентно)
POST    — создавать новые ресурсы
PUT     — полностью заменять ресурс
PATCH   — частично обновлять ресурс
DELETE  — удалять ресурс
HEAD    — как GET, но без тела ответа
OPTIONS — получить доступные методы

3. Представления (Representations)

# Один ресурс может быть представлен по-разному

# JSON представление
GET /api/users/42
Accept: application/json
Response:
{
    "id": 42,
    "name": "Alice",
    "email": "alice@example.com"
}

# XML представление
GET /api/users/42
Accept: application/xml
Response:
<?xml version="1.0"?>
<user>
    <id>42</id>
    <name>Alice</name>
    <email>alice@example.com</email>
</user>

# Клиент говорит серверу, в каком формате ему нужен ресурс

4. Stateless коммуникация

# Каждый запрос содержит всю нужную информацию
# Сервер не хранит контекст клиента между запросами

# ❌ Неправильно — зависит от сессии
GET /api/orders
# Результат зависит от текущей сессии пользователя

# ✅ Правильно — всё в запросе
GET /api/users/42/orders
Authorization: Bearer token123
# Сервер получает всю информацию для ответа

Практические примеры

REST API для блога

# FastAPI
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

# Модель ресурса
class Post(BaseModel):
    title: str
    content: str
    author_id: int

# Базы данных (в памяти для примера)
posts = {}
post_counter = 0

# CREATE — создание нового ресурса
@app.post("/api/posts")  # POST /api/posts
def create_post(post: Post):
    global post_counter
    post_counter += 1
    posts[post_counter] = post
    return {"id": post_counter, **post.dict()}

# READ — получение ресурса
@app.get("/api/posts/{post_id}")  # GET /api/posts/1
def get_post(post_id: int):
    if post_id not in posts:
        raise HTTPException(status_code=404, detail="Post not found")
    return {"id": post_id, **posts[post_id].dict()}

# READ LIST — получение всех ресурсов
@app.get("/api/posts")  # GET /api/posts
def list_posts():
    return [{"id": pid, **p.dict()} for pid, p in posts.items()]

# UPDATE — обновление ресурса
@app.put("/api/posts/{post_id}")  # PUT /api/posts/1
def update_post(post_id: int, post: Post):
    if post_id not in posts:
        raise HTTPException(status_code=404, detail="Post not found")
    posts[post_id] = post
    return {"id": post_id, **post.dict()}

# DELETE — удаление ресурса
@app.delete("/api/posts/{post_id}")  # DELETE /api/posts/1
def delete_post(post_id: int):
    if post_id not in posts:
        raise HTTPException(status_code=404, detail="Post not found")
    del posts[post_id]
    return {"message": "Post deleted"}

Django REST Framework пример

from rest_framework import viewsets
from rest_framework.decorators import action
from .serializers import UserSerializer
from .models import User

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
    # Автоматически создаёт:
    # GET    /api/users/          (list)
    # POST   /api/users/          (create)
    # GET    /api/users/{id}/     (retrieve)
    # PUT    /api/users/{id}/     (update)
    # DELETE /api/users/{id}/     (destroy)
    
    @action(detail=True, methods=['post'])
    def set_password(self, request, pk=None):
        # Кастомное действие
        # POST /api/users/{id}/set_password/
        user = self.get_object()
        user.set_password(request.data['password'])
        user.save()
        return Response({'status': 'password set'})

Важные принципы REST

1. Ресурсы идентифицируются URL

Каждый ресурс имеет уникальный адрес:

/api/users/42           — конкретный пользователь
/api/posts/1/comments/5 — комментарий 5 к посту 1
/api/products/abc123    — продукт с ID abc123

2. Стандартные HTTP коды ответа

# 2xx — Успех
200 OK              — Запрос успешен
201 Created         — Ресурс создан
204 No Content      — Успех, но нет тела ответа

# 4xx — Ошибка клиента
400 Bad Request     — Неверные данные
401 Unauthorized    — Нужна авторизация
403 Forbidden       — Доступ запрещён
404 Not Found       — Ресурс не найден
409 Conflict        — Конфликт (например, дубликат)

# 5xx — Ошибка сервера
500 Internal Error  — Ошибка на сервере
503 Service Unavailable  — Сервис недоступен

3. Методы безопасны и идемпотентны

Bезопасные методы (не меняют состояние):
GET, HEAD, OPTIONS

Идемпотентные методы (один результат при повторении):
GET, PUT, DELETE

Небезопасные и неидемпотентные:
POST (создаёт новый ресурс каждый раз)

Вложенные ресурсы

# Правильно — вложенные ресурсы
GET /api/users/42/posts          # Посты пользователя 42
GET /api/users/42/posts/1        # Пост 1 пользователя 42
GET /api/posts/1/comments        # Комментарии поста 1
POST /api/posts/1/comments       # Добавить комментарий к посту 1

# Неправильно — глубокая вложенность
GET /api/users/42/posts/1/comments/5/author/10  # Слишком глубоко

# Альтернатива
GET /api/comments/5              # Прямой доступ к комментарию

Фильтрация, сортировка, пагинация

# Фильтрация через query параметры
GET /api/users?role=admin        # Только администраторы
GET /api/posts?author_id=42      # Посты автора 42
GET /api/products?price_min=100&price_max=500

# Сортировка
GET /api/posts?sort=created_at   # По дате создания
GET /api/posts?sort=-created_at  # По дате, убывающе

# Пагинация
GET /api/posts?page=1&limit=10   # Первая страница, 10 элементов
GET /api/posts?offset=20&limit=10 # Начиная с элемента 20

# Выборка полей
GET /api/users?fields=id,name,email  # Только нужные поля

Версионирование API

# Вариант 1: URL версионирование
GET /api/v1/users
GET /api/v2/users    # Другая версия

# Вариант 2: Header версионирование
GET /api/users
Accept: application/vnd.myapp.v2+json

# Вариант 3: Query параметр
GET /api/users?api_version=2

Ошибки при проектировании REST API

# ❌ Неправильно — глаголы в URL
GET /api/getUser              # Глагол не нужен
POST /api/createUser          # Используй HTTP метод
GET /api/deleteUser?id=42     # DELETE уже есть

# ✅ Правильно — только существительные
GET /api/users                # Получить
POST /api/users               # Создать
GET /api/users/42             # Получить конкретного
DELETE /api/users/42          # Удалить

# ❌ Неправильно — статус в теле ответа
{
    "status": "error",
    "httpCode": 200            # Противоречие!
}

# ✅ Правильно — статус в HTTP коде
HTTP 400 Bad Request
{
    "error": "Invalid input"
}

REST vs RPC

# RPC стиль (старый подход)
POST /api/user.get?id=42
POST /api/user.create
POST /api/user.delete?id=42

# REST стиль (правильный)
GET /api/users/42
POST /api/users
DELETE /api/users/42

# Различие:
# RPC — акцент на действия (функции)
# REST — акцент на ресурсы

Best Practice

# 1. Используй существительные во множественном числе
GET /api/users       # не /api/user
GET /api/products    # не /api/product

# 2. Используй иерархию для вложенных ресурсов
GET /api/users/42/posts        # Посты пользователя 42
GET /api/posts/1/comments      # Комментарии поста 1

# 3. Используй стандартные HTTP коды
200 OK для успеха
201 Created для создания
400 Bad Request для ошибок клиента
500 Internal Server Error для ошибок сервера

# 4. Версионируй API
/api/v1/users   # Первая версия
/api/v2/users   # Вторая версия

# 5. Документируй API
# Используй Swagger/OpenAPI

# 6. Возвращай JSON (стандарт)
# XML устаревший