localhost в build_absolute_uri для Django с Nginx - PullRequest
0 голосов
/ 22 сентября 2019

На производстве я использую цепь Django - UWSGI - Docker - Nxing.UWSGI работает с портом 50012, а Ngxin настроен следующим образом:

proxy_pass http://localhost:50012;

Процесс Django считает, что его хост - localhost:50012 вместо домена, который слушает Nginx.Поэтому, когда вызывается функция build_absolute_uri, вместо моего домена localhost:50012.Есть ли способ заставить Django использовать пользовательское имя хоста при вызове build_absolute_uri?

Замечание : в некоторых библиотеках build_absolute_uri вызывается неявно (например, social-django или пример)так что избегать этой функции не является решением в моем случае.

1 Ответ

1 голос
/ 22 сентября 2019

Проблема

Когда общедоступное имя хоста, которое вы используете для доступа к прокси, отличается от внутреннего имени хоста сервера приложений, Django не может узнать, какое имя хоста использовалось в исходном запросе, если прокси не проходитвместе с этой информацией.

Возможные решения

1) Установите прокси-сервер для прохождения по оригинальному хосту

От MDN :

Заголовок X-Forwarded-Host (XFH) является де-факто стандартным заголовком для идентификации исходного хоста, запрошенного клиентом в заголовке HTTP-запроса хоста.

Имена хостов и порты обратных прокси (балансировщики нагрузки (CDN) могут отличаться от исходного сервера, обрабатывающего запрос, в этом случае заголовок X-Forwarded-Host полезен для определения того, какой хост был изначально использован.

Есть две вещи, которые вам следуетdo:

  1. убедитесь, что все прокси перед Django проходят вдоль X-Forwarded-Host header
  2. включите USE_X_FORWARDED_HOST в настройках
  3. есливнутренняя и внешняя схемы также различаются, установите SECURE_PROXY_SSL_HEADER в значащее значение и настройте сервер на отправку соответствующего заголовка

Когда USE_X_FORWARDED_HOST установлено в True в settings.py,HttpRequest.build_absolute_uri использует заголовок X-Forwarded-Host вместо request.META['HTTP_HOST'] или request.META['SERVER_NAME'].

Я не буду слишком углубляться в настройку прокси-сервера (поскольку это больше относится к профессиональному сетевому администрированию, чем к программированию наобласть действия этого сайта), но для nginx это должно быть что-то вроде:

location / {
    ...
    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    ...
    proxy_pass http://upstream:port;
}    

Вероятно, лучшее решение, так как оно полностью динамическое, вам не нужно ничего менять, если изменяется публичная схема / имя хоста вбудущее.

Если внутренняя и внешняя схемы также различаются, вы можете установить SECURE_PROXY_SSL_HEADER в settings.py примерно так:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

А затем добавить следующее кконфигурация сервера:

Forwarded-Proto: https;

2) Использовать одно и то же имя хоста для публичных и частных серверов

Допустим, ваше общедоступное имя хоста - "host.example.com": вы можете добавить строку вродеэто к вашему /etc/hosts (в Windows %windir%\System32\drivers\etc\hosts):

127.0.0.1    host.example.com

Теперь вы можете использовать имя хоста в конфигурации nginx:

proxy_pass http://host.example.com:port;

Когда внутренняя и внешняя схемы также различаются (внешние https(внутренний http), вы можете установить SECURE_PROXY_SSL_HEADER, как описано в первом решении.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...