Экзаменационные практики
Практические задания: FastAPI (реализация кода)
Задание 1. Создание базового приложения
Напишите минимальное FastAPI-приложение с эндпойнтом GET /, который возвращает JSON {"message": "Hello, World!"}.
# Допишите код:from fastapi import FastAPI
app = FastAPI()
# Ваш код здесьЗадание 2. Pydantic-модель для валидации
Создайте Pydantic-модель Product со следующими полями:
name(str, обязательное, минимум 1 символ)price(float, обязательное, больше 0)quantity(int, по умолчанию 0, >= 0)category(str, опциональное)
from pydantic import BaseModel, Fieldfrom typing import Optional
# Ваш код здесьclass Product(BaseModel): passЗадание 3. POST-эндпойнт для создания ресурса
Реализуйте эндпойнт POST /products/, который:
- Принимает JSON с данными продукта (модель
ProductCreate) - Генерирует UUID для нового продукта
- Сохраняет в словарь
DB - Возвращает созданный продукт с кодом
201 Created
from fastapi import FastAPI, statusfrom uuid import uuid4, UUIDfrom pydantic import BaseModel
app = FastAPI()DB: dict = {}
class ProductCreate(BaseModel): name: str price: float
class Product(ProductCreate): id: UUID
# Ваш код здесь@app.post("/products/", ...)def create_product(...): passЗадание 4. GET с параметрами запроса (Query)
Реализуйте эндпойнт GET /products/, который:
- Поддерживает параметры
min_price,max_price(фильтрация по цене) - Поддерживает параметр
limit(по умолчанию 10, от 1 до 100) - Возвращает отфильтрованный список продуктов
from fastapi import FastAPI, Queryfrom typing import Optional, List
# Ваш код здесь@app.get("/products/", response_model=List[Product])def list_products( # Опишите параметры): passЗадание 5. GET по ID с обработкой 404
Реализуйте эндпойнт GET /products/{product_id}, который:
- Принимает
product_idтипа UUID - Возвращает продукт, если найден
- Возвращает
404 Not Foundс сообщением, если продукт не найден
from fastapi import FastAPI, HTTPException, Pathfrom uuid import UUID
# Ваш код здесь@app.get("/products/{product_id}")def get_product(product_id: UUID): passЗадание 6. PATCH для частичного обновления
Реализуйте эндпойнт PATCH /products/{product_id}, который:
- Принимает модель
ProductUpdate(все поля опциональные) - Обновляет только переданные поля
- Возвращает обновлённый продукт
from pydantic import BaseModelfrom typing import Optional
class ProductUpdate(BaseModel): name: Optional[str] = None price: Optional[float] = None
# Ваш код здесь@app.patch("/products/{product_id}")def update_product(product_id: UUID, payload: ProductUpdate): passЗадание 7. DELETE с кодом 204
Реализуйте эндпойнт DELETE /products/{product_id}, который:
- Удаляет продукт по ID
- Возвращает код
204 No Contentпри успехе - Возвращает
404 Not Found, если продукт не найден
from fastapi import status
# Ваш код здесь@app.delete("/products/{product_id}", status_code=...)def delete_product(product_id: UUID): passЗадание 8. Dependency Injection для работы с БД
Реализуйте функцию-зависимость get_db(), которая:
- Создаёт сессию базы данных
- Возвращает её через
yield - Закрывает сессию в блоке
finally
from fastapi import Dependsfrom sqlalchemy.orm import Session
def get_db(): # Ваш код здесь pass
@app.get("/items/")def get_items(db: Session = Depends(get_db)): passЗадание 9. JWT-аутентификация
Реализуйте функцию create_access_token(), которая:
- Принимает
user_idи опциональныйexpires_delta - Создаёт JWT с полями
sub,exp,iat - Возвращает закодированный токен
import jwtfrom datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"ALGORITHM = "HS256"
def create_access_token(user_id: str, expires_delta: timedelta = None) -> str: # Ваш код здесь passЗадание 10. Защита эндпойнта с JWT
Реализуйте зависимость verify_token(), которая:
- Извлекает токен из заголовка
Authorization: Bearer <token> - Декодирует и валидирует JWT
- Возвращает
401 Unauthorizedпри невалидном/просроченном токене - Возвращает payload токена при успехе
from fastapi import Depends, HTTPException, statusfrom fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
security = HTTPBearer()
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)): # Ваш код здесь pass
@app.get("/protected/")def protected_route(payload: dict = Depends(verify_token)): return {"user_id": payload["sub"]}Задание 11. Хеширование паролей
Реализуйте функции hash_password() и verify_password() с использованием bcrypt:
import bcrypt
def hash_password(password: str) -> str: # Ваш код здесь pass
def verify_password(plain_password: str, hashed_password: str) -> bool: # Ваш код здесь passЗадание 12. RBAC (Role-Based Access Control)
Реализуйте декоратор/зависимость require_role(), который:
- Проверяет роль пользователя из JWT
- Возвращает
403 Forbidden, если роль не соответствует требуемой
from enum import Enum
class Role(str, Enum): ADMIN = "admin" USER = "user"
def require_role(required_role: Role): def checker(payload: dict = Depends(verify_token)): # Ваш код здесь pass return checker
@app.delete("/admin/users/{user_id}")def delete_user(user_id: int, user = Depends(require_role(Role.ADMIN))): passЗадание 13. Обработка ошибок валидации
Создайте кастомный обработчик исключений для RequestValidationError, который возвращает ошибки в формате:
{ "error": { "code": "VALIDATION_ERROR", "message": "Ошибка валидации данных", "details": [...] }}from fastapi import FastAPIfrom fastapi.exceptions import RequestValidationErrorfrom fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(RequestValidationError)async def validation_exception_handler(request, exc): # Ваш код здесь passЗадание 14. Rate Limiting
Реализуйте простой Rate Limiter, который ограничивает количество запросов с одного IP до 10 в минуту:
from fastapi import Request, HTTPExceptionfrom collections import defaultdictfrom datetime import datetime, timedelta
# Хранилище запросов: {ip: [timestamp1, timestamp2, ...]}request_counts = defaultdict(list)
async def rate_limit_middleware(request: Request, call_next): # Ваш код здесь pass