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

Как Django приложение получает запрос от прокси сервера?

2.0 Middle🔥 181 комментариев
#DevOps и инфраструктура#Django

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

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

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

Получение запроса Django приложением через прокси сервер

Архитектура запроса через прокси

Когда Django приложение стоит за прокси сервером (Nginx, Apache или другой обратный прокси), запрос проходит несколько этапов обработки. Давайте разберём полный цикл.

Как работает прокси сервер

Прокси сервер действует как промежуточное звено между клиентом и Django приложением:

# Цикл запроса:
# Клиент (браузер) 
#   ↓ (HTTP запрос)
# Прокси сервер (Nginx/Apache)
#   ↓ (проксирует на WSGI сервер)
# WSGI сервер (Gunicorn/uWSGI)
#   ↓ (передаёт в Django)
# Django приложение
#   ↓ (обработка)
# Ответ идёт в обратном порядке

WSGI интерфейс

Django приложение работает через WSGI (Web Server Gateway Interface). Прокси отправляет запрос на WSGI сервер (обычно Gunicorn или uWSGI), который вызывает Django application:

# Пример простого WSGI приложения
def application(environ, start_response):
    # environ — словарь с информацией о запросе
    # Включает: REQUEST_METHOD, PATH_INFO, QUERY_STRING и т.д.
    
    status = '200 OK'
    response = b'Hello World'
    response_headers = [('Content-type', 'text/plain')]
    
    start_response(status, response_headers)
    return [response]

Как Django получает запрос

Django через свой WSGI middleware получает environ словарь от WSGI сервера:

# django/core/wsgi.py
from django.core.handlers.wsgi import WSGIHandler

application = WSGIHandler()

WSGIHandler парсит environ и создаёт объект HttpRequest:

# Упрощённо (внутри Django):
class HttpRequest:
    def __init__(self, environ):
        self.method = environ['REQUEST_METHOD']
        self.path = environ['PATH_INFO']
        self.query_string = environ.get('QUERY_STRING', '')
        self.META = environ  # Всё с префиксом HTTP_
        # И другие параметры

Работа с прокси: заголовки X-Forwarded-*

Ключевой момент: прокси сервер должен передавать оригинальный IP клиента и схему запроса через специальные заголовки:

# Конфиг Nginx:
location / {
    proxy_pass http://127.0.0.1:8000;
    
    # Критично для Django!
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $server_name;
}

Django обрабатывает эти заголовки через REMOTE_ADDR и HTTP_X_FORWARDED_FOR:

# Получение реального IP клиента
def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    
    if x_forwarded_for:
        # Может быть несколько IP (через запятую)
        ip = x_forwarded_for.split(',')[0].strip()
    else:
        ip = request.META.get('REMOTE_ADDR')
    
    return ip

Важные настройки Django для работы за прокси

# settings.py

# Доверяемые прокси (обычно localhost:8000)
TRUSTED_PROXIES = ['127.0.0.1', 'localhost']

# Для получения реального хоста
USE_X_FORWARDED_HOST = True

# Для получения реальной схемы (http/https)
USE_X_FORWARDED_PROTO = True

# Для безопасности с HTTPS за прокси
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Запуск с Gunicorn

# Типичный запуск Django за прокси:
gunicorn \
    --workers 4 \
    --bind 127.0.0.1:8000 \
    --worker-class sync \
    myproject.wsgi:application

Gunicorn слушает только на локальном порту (127.0.0.1:8000), Nginx получает запрос извне и проксирует на Gunicorn.

Логирование и отладка

# Для отладки, какие данные получает Django:
def debug_request(request):
    print(f'Method: {request.method}')
    print(f'Path: {request.path}')
    print(f'Remote Addr: {request.META.get("REMOTE_ADDR")}')
    print(f'X-Forwarded-For: {request.META.get("HTTP_X_FORWARDED_FOR")}')
    print(f'Host: {request.META.get("HTTP_HOST")}')
    print(f'Scheme: {request.scheme}')  # http или https

Резюме

Django получает запрос через WSGI интерфейс от приложения-сервера (Gunicorn/uWSGI). Прокси сервер преобразует HTTP запрос в вызов WSGI приложения и передаёт информацию об оригинальном клиенте через заголовки X-Forwarded-*. Django парсит эти заголовки и восстанавливает контекст оригинального запроса. Правильная конфигурация обоих компонентов критична для безопасности и правильной работы приложения.