Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
REST: Representational State Transfer
REST расшифровывается как "Representational State Transfer" — архитектурный стиль для построения веб-сервисов.
Хотя аббревиатура звучит сложно, концепция очень простая: веб-сервис работает как набор ресурсов, которыми манипулируют с помощью стандартных HTTP методов.
Три ключевых компонента
1. Representational (Представление)
Ресурс представлен в определённом формате:
- JSON (самый популярный сейчас)
- XML (устаревший, но всё ещё используется)
- HTML
- Plain text
# Один ресурс User может быть представлен как:
# JSON
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
# XML
<user>
<id>1</id>
<name>Alice</name>
<email>alice@example.com</email>
</user>
2. State (Состояние)
Клиент и сервер обмениваются представлениями состояния ресурса:
- Каждый запрос содержит ВСЮ информацию для обработки
- Сервер НЕ хранит состояние клиента между запросами (stateless)
- Следующий запрос независим от предыдущего
# Запрос 1: получаем текущее состояние
GET /api/v1/users/1
# Ответ: полное представление User
# Запрос 2: обновляем состояние
PUT /api/v1/users/1
{
"name": "Alice Updated",
"email": "alice.new@example.com"
}
# Ответ: новое полное представление User
3. Transfer (Передача)
Передача состояния происходит через HTTP протокол:
- GET — получить представление
- POST — создать новый ресурс
- PUT/PATCH — обновить существующий
- DELETE — удалить ресурс
REST в действии: Пример
# FastAPI приложение — идеально для REST
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
id: int
name: str
email: str
# 1. GET — получить все ресурсы (представление коллекции)
@app.get("/users")
async def list_users():
# Представление: список всех пользователей
return [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"},
]
# 2. GET — получить один ресурс (представление одного)
@app.get("/users/{user_id}")
async def get_user(user_id: int):
# Представление: один пользователь
return {"id": user_id, "name": "Alice", "email": "alice@example.com"}
# 3. POST — создать новый ресурс (отправляем представление нового состояния)
@app.post("/users")
async def create_user(user: User):
# Создаём новый ресурс с переданным представлением
user.id = 3 # Сервер генерирует ID
return user
# 4. PUT — обновить весь ресурс (отправляем новое полное представление)
@app.put("/users/{user_id}")
async def update_user(user_id: int, user: User):
# Заменяем ВСЁ представление пользователя
user.id = user_id
return user
# 5. PATCH — обновить часть ресурса (отправляем только изменения)
@app.patch("/users/{user_id}")
async def partial_update(user_id: int, data: dict):
# Обновляем только переданные поля
return {"id": user_id, "name": data.get("name"), ...}
# 6. DELETE — удалить ресурс
@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
# Удаляем ресурс, ничего не возвращаем (204 No Content)
return {}
REST принципы (RFC 7231)
1. Клиент-Сервер архитектура
Клиент Сервер
| |
|------ HTTP GET -------->|
| (обработка)
|<---- JSON/XML ---------|
2. Stateless (без состояния)
# ❌ Плохо: сервер запомнил пользователя
logged_in_users = {}
@app.post("/login")
def login(user: str):
logged_in_users[user] = True # Запомнили в памяти
return {"status": "logged in"}
# ✅ Хорошо: каждый запрос содержит токен
@app.get("/profile")
def get_profile(token: str): # Токен в каждом запросе
user = verify_token(token)
return {"profile": ...}
3. Кэшируемость (Cacheable)
# Ответы помечаются как кэшируемые или нет
@app.get("/users/{user_id}")
async def get_user(user_id: int):
# Эта операция идемпотентна (всегда один результат)
# Браузер может кэшировать результат
return {"id": user_id, "name": "Alice"}
# HTTP заголовок:
# Cache-Control: max-age=3600 (кэшировать на час)
4. Единообразный интерфейс
Одинаковый способ работы со всеми ресурсами:
GET /users — список
GET /users/1 — один
POST /users — создать
PUT /users/1 — обновить
DELETE /users/1 — удалить
GET /products — список
GET /products/5 — один
POST /products — создать
PUT /products/5 — обновить
DELETE /products/5 — удалить
REST коды ответов (HTTP статусы)
| Код | Смысл | Пример |
|---|---|---|
| 200 OK | Успешно | GET user вернул данные |
| 201 Created | Создано | POST создал новый ресурс |
| 204 No Content | Успешно, но ничего | DELETE удалил |
| 400 Bad Request | Ошибка клиента | Неверный JSON |
| 404 Not Found | Не найдено | GET несуществующий ID |
| 500 Server Error | Ошибка сервера | Crash в обработчике |
Пример: Полная REST API для блога
from fastapi import FastAPI, HTTPException
from typing import List
app = FastAPI()
class Post(BaseModel):
id: int
title: str
content: str
author: str
posts_db = {}
# СПИСОК постов
@app.get("/posts")
async def list_posts() -> List[Post]:
return list(posts_db.values())
# ОДИН пост
@app.get("/posts/{post_id}")
async def get_post(post_id: int) -> Post:
if post_id not in posts_db:
raise HTTPException(status_code=404, detail="Post not found")
return posts_db[post_id]
# СОЗДАТЬ пост
@app.post("/posts")
async def create_post(post: Post) -> Post:
posts_db[post.id] = post
return post
# ОБНОВИТЬ пост
@app.put("/posts/{post_id}")
async def update_post(post_id: int, post: Post) -> Post:
if post_id not in posts_db:
raise HTTPException(status_code=404, detail="Post not found")
post.id = post_id
posts_db[post_id] = post
return post
# УДАЛИТЬ пост
@app.delete("/posts/{post_id}")
async def delete_post(post_id: int):
if post_id not in posts_db:
raise HTTPException(status_code=404, detail="Post not found")
del posts_db[post_id]
return {"status": "deleted"}
REST vs SOAP vs GraphQL
| Характеристика | REST | SOAP | GraphQL |
|---|---|---|---|
| Простота | Просто | Сложно | Средне |
| Гибкость | Средняя | Средняя | Высокая |
| Кэширование | Встроено в HTTP | Нет | Нет |
| Выучивание | Быстро | Медленно | Медленно |
| Использование | 90% современных API | Легаси | Новые проекты |
Важные замечания
1. REST — не база данных
# ❌ Неправильное название
GET /api/v1/getUserById?id=1 # Глагол (неправильно)
GET /api/v1/users?id=1 # Существительное (правильно)
GET /api/v1/createUser # Глагол (неправильно)
POST /api/v1/users # HTTP метод + существительное (правильно)
2. REST требует правильных HTTP методов
# ❌ Плохо: всё через GET
GET /api/delete_user?id=1
# ✅ Хорошо: используй DELETE
DELETE /api/users/1
3. Версионирование API
# Версия в пути (популярный способ)
GET /api/v1/users # старая версия
GET /api/v2/users # новая версия
# Версия в заголовке (более чистый способ)
GET /api/users
Accept-Version: 2.0
Вывод
REST — архитектурный стиль, где:
- Всё — ресурсы (существительные)
- Операции — HTTP методы (GET, POST, PUT, DELETE)
- Общение — Representation (JSON, XML)
- Сервер — Stateless (не запоминает клиентов)
Это сделало веб стандартным и простым для всех разработчиков.