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

Расскажи про архитектуру веб-приложений на примере REST

2.0 Middle🔥 221 комментариев
#REST API и HTTP

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

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

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

Архитектура веб-приложений на примере REST

REST (Representational State Transfer) — архитектурный стиль для построения масштабируемых веб-приложений, основанный на HTTP протоколе. Рассмотрим основные компоненты архитектуры.

Принципы REST

  • Client-Server: клиент и сервер разделены, независимо эволюционируют
  • Stateless: каждый запрос содержит всю необходимую информацию
  • Cacheable: ответы помечаются как кэшируемые или нет
  • Uniform Interface: единообразный интерфейс для взаимодействия
  • Layered System: архитектура состоит из слоёв
  • Code on Demand (опционально): сервер может отправлять код клиенту

Типичная архитектура REST приложения

Клиент (Frontend/Mobile)
    |
    v
[HTTP Request]
    |
    v
API Gateway / Load Balancer
    |
    v
Web Server (nginx/Apache)
    |
    v
Application Layer (Django/FastAPI)
    |
    v
Business Logic Layer (Services)
    |
    v
Data Access Layer (ORM/Repository)
    |
    v
Database (PostgreSQL/MySQL)

Слоистая архитектура на примере FastAPI

Presentation Layer (Presentation/API)

Отвечает за обработку HTTP запросов и ответов:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    email: str

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

@app.post("/api/v1/users", response_model=UserResponse)
async def create_user(user: UserCreate):
    # Валидация уже произошла (Pydantic)
    result = await user_service.create(user)
    return result

Application/Business Logic Layer

Содержит бизнес-логику, использует сервисы:

class UserService:
    def __init__(self, repository: UserRepository):
        self.repository = repository
    
    async def create(self, user_data: UserCreate) -> User:
        # Проверка по email
        existing = await self.repository.find_by_email(user_data.email)
        if existing:
            raise ValueError("Email уже зарегистрирован")
        
        # Хеширование пароля, бизнес-логика
        user = User(
            name=user_data.name,
            email=user_data.email
        )
        return await self.repository.save(user)
    
    async def get_by_id(self, user_id: int) -> User:
        user = await self.repository.find_by_id(user_id)
        if not user:
            raise UserNotFound(f"User {user_id} not found")
        return user

Data Access Layer (Repository Pattern)

Отвечает за работу с БД, скрывает детали реализации:

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

class UserRepository:
    def __init__(self, session: AsyncSession):
        self.session = session
    
    async def save(self, user: User) -> User:
        self.session.add(user)
        await self.session.commit()
        await self.session.refresh(user)
        return user
    
    async def find_by_id(self, user_id: int) -> User:
        query = select(UserModel).where(UserModel.id == user_id)
        result = await self.session.execute(query)
        return result.scalar_one_or_none()
    
    async def find_by_email(self, email: str) -> User:
        query = select(UserModel).where(UserModel.email == email)
        result = await self.session.execute(query)
        return result.scalar_one_or_none()

HTTP Методы в REST

МетодОперацияИдемпотентныйБезопасный
GETЧтениеДаДа
POSTСозданиеНетНет
PUTЗаменаДаНет
PATCHОбновлениеНетНет
DELETEУдалениеДаНет
@app.get("/api/v1/users/{user_id}")  # Чтение
async def get_user(user_id: int):
    return await user_service.get_by_id(user_id)

@app.post("/api/v1/users")  # Создание
async def create_user(user: UserCreate):
    return await user_service.create(user)

@app.put("/api/v1/users/{user_id}")  # Полное обновление
async def update_user(user_id: int, user: UserUpdate):
    return await user_service.update(user_id, user)

@app.patch("/api/v1/users/{user_id}")  # Частичное обновление
async def patch_user(user_id: int, user: UserPatch):
    return await user_service.patch(user_id, user)

@app.delete("/api/v1/users/{user_id}")  # Удаление
async def delete_user(user_id: int):
    await user_service.delete(user_id)
    return {"status": "deleted"}

Состояние HTTP (статус коды)

  • 2xx: Успех (200 OK, 201 Created, 204 No Content)
  • 3xx: Редирект (301, 302, 304)
  • 4xx: Ошибка клиента (400 Bad Request, 404 Not Found, 401 Unauthorized)
  • 5xx: Ошибка сервера (500 Internal Server Error, 503 Service Unavailable)
from fastapi import status

@app.post("/api/v1/users", status_code=status.HTTP_201_CREATED)
async def create_user(user: UserCreate):
    return await user_service.create(user)

Обработка ошибок

from fastapi import HTTPException

class UserNotFound(Exception):
    pass

@app.exception_handler(UserNotFound)
async def user_not_found_handler(request, exc):
    return JSONResponse(
        status_code=404,
        content={"detail": str(exc)}
    )

@app.get("/api/v1/users/{user_id}")
async def get_user(user_id: int):
    user = await user_service.get_by_id(user_id)
    if not user:
        raise UserNotFound(f"User {user_id} not found")
    return user

Зависимости и инъекция

from fastapi import Depends

async def get_user_service() -> UserService:
    repository = UserRepository(session)
    return UserService(repository)

@app.get("/api/v1/users/{user_id}")
async def get_user(user_id: int, service: UserService = Depends(get_user_service)):
    return await service.get_by_id(user_id)

Масштабируемость и оптимизация

  • Кэширование: Redis для часто используемых данных
  • Пагинация: для больших наборов данных
  • Асинхронность: async/await для высокой пропускной способности
  • Rate limiting: защита от перегрузок
  • Версионирование API: /api/v1/, /api/v2/
from fastapi import Query

@app.get("/api/v1/users")
async def list_users(
    skip: int = Query(0, ge=0),
    limit: int = Query(10, ge=1, le=100)
):
    return await user_service.list(skip=skip, limit=limit)

REST архитектура обеспечивает масштабируемость, простоту интеграции и понятный контракт между клиентом и сервером.

Расскажи про архитектуру веб-приложений на примере REST | PrepBro