====== 2.5 Создайте файл app.py ====== nano app.py """ Модуль приложения для тестирования цепочек обратных прокси NGINX. Задача: Принимать HTTP запросы и показывать содержимое заголовка X-Forwarded-For, что позволяет проверить корректность передачи IP адресов через цепочку прокси. """ from fastapi import FastAPI, Request from typing import Dict, Any # Создаём экземпляр FastAPI приложения # FastAPI автоматически предоставляет: # - Документацию по адресу /docs # - Валидацию данных # - Асинхронную обработку запросов app = FastAPI( title="NGINX Chain Test", description="Приложение для проверки передачи X-Forwarded-For через цепочку прокси", version="1.0.0" ) @app.get("/") @app.post("/") @app.get("/health") async def root(request: Request) -> Dict[str, Any]: """ Основной endpoint для тестирования. Аргументы: request: Объект Request от FastAPI, содержащий все данные запроса Возвращает: Словарь с информацией о заголовке X-Forwarded-For и IP клиента Важно: FastAPI получает заголовки уже после обработки NGINX, поэтому мы видим именно тот X-Forwarded-For, который передали прокси. """ # Извлекаем заголовок X-Forwarded-For из запроса # Если заголовок отсутствует, возвращаем "Not present" xff_header = request.headers.get("x-forwarded-for", "Not present") # request.client.host показывает IP адрес, с которым NGINX соединился с приложением # Это будет IP последнего прокси в цепочке client_ip = request.client.host if request.client else "Unknown" return { "message": "X-Forwarded-For header received", "value": xff_header, "client_ip": client_ip, "explanation": { "xff_example": "Формат: IP_пользователя, IP_прокси1, IP_прокси2, ...", "client_ip_meaning": f"Последний прокси в цепочке (IP: {client_ip})" } } @app.get("/headers") async def headers(request: Request) -> Dict[str, str]: """ Вспомогательный endpoint для отладки. Возвращает ВСЕ заголовки запроса в виде словаря. Полезно для: - Проверки других заголовков (X-Real-IP, X-Forwarded-Proto и т.д.) - Отладки проблем с проксированием """ # Преобразуем заголовки в обычный словарь для удобного вывода return dict(request.headers) @app.get("/debug") async def debug_info(request: Request) -> Dict[str, Any]: """ Расширенная отладочная информация. Возвращает: - Все заголовки - IP клиента (со стороны приложения) - Метод запроса - Путь запроса """ return { "headers": dict(request.headers), "client_ip": request.client.host if request.client else None, "method": request.method, "url_path": request.url.path, "query_params": dict(request.query_params) }