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)
}