Я пытаюсь сделать свое веб-приложение (на основе Django/wsgi) доступным из некоторой подпапки основного домена.
Я использую докер для своего приложения и статические файлы, поэтому у меня есть основной nginx на моем сервере в качестве обратного прокси-сервера, еще один nginx в контейнере «nginx», который направляет данные для моего приложения, и uWSGI во втором контейнере, который обслуживает фактические данные Django.

И я хочу, чтобы мое приложение было доступно извне как myserver.com/mytool, в то же время я не хочу жестко кодировать mytool где-либо в своем приложении. Обычно для такого рода вещей используется заголовок SCRIPT_NAME, поэтому вот конфигурация nginx на хосте:
server {
listen 80; # Just for sake of simplicity, of course in production it's 443 with SSL
location /mytool/ {
proxy_pass http://127.0.0.1:8000/;
include proxy_params;
proxy_set_header SCRIPT_NAME /mytool; # <--- Here I define my header which backend should use
}
}
Затем в моем docker-compose я выставляю 8000:80 для nginx и вот внутренняя конфигурация nginx:
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
}
}
С этой конфигурацией я ожидал бы, что мое приложение Django получит заголовок SCRIPT_NAME, но, по-видимому, это не так.
В то же время, если я определяю пользовательские заголовки, такие как proxy_set_header X-something something;, тогда они перенаправляются правильно, и я могу видеть это из Django.
Как мне передать SCRIPT_NAME, чтобы избежать жесткого кода пути в моем коде?





Здесь есть две проблемы.
Во-первых, nginx считает заголовки, содержащие символы подчеркивания, недопустимыми, поэтому заголовок SCRIPT_NAME не принимается nginx в контейнере, потому что он недействителен с точки зрения nginx. К счастью, директива nginx underscores_in_headers здесь, чтобы помочь.
Просто добавьте underscores_in_headers on; в server раздел nginx внутри Докера (не в хост).
Когда это будет сделано, возникает еще одна проблема — nginx пересылает заголовок, добавляя HTTP перед своим именем. Итак, теперь со стороны Django вы увидите HTTP_SCRIPT_NAME вместо SCRIPT_NAME. Но опять же, к счастью для нас, это можно легко исправить, снова используя строку uwsgi_param SCRIPT_NAME $http_script_name; в nginx внутри Docker.
Таким образом, окончательный конфиг nginx внутри Docker должен выглядеть так:
server {
underscores_in_headers on; # <---- (1)
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
uwsgi_param SCRIPT_NAME $http_script_name; # <--- (2)
}
}
В Джанго settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/static'
# Bug in Django of not using SCRIPT_NAME header...
# See https://code.djangoproject.com/ticket/25598
# Let's implement dirty workaround for now
if os.getenv('SCRIPT_NAME'):
STATIC_URL = os.getenv('SCRIPT_NAME') + STATIC_ROOT
@AndrewLi Только что проверил - у меня действительно ничего особенного в конфиге... [uwsgi] socket = :3031 wsgi-file = my_project/wsgi.py processes = 4 threads = 2 # Default size is too low buffer-size = 32768
@AndrewLi добавлен настройками Django, но упомянутая проблема была исправлена в Django 3.1 мной, поэтому для 3.1+ она не нужна.
Привет @The Godfater, я сейчас сталкиваюсь с этой проблемой, как и ты. Тем не менее, я изменил настройки, которые вы предложили, но они все еще не работают для меня. Не могли бы вы поделиться своей конфигурацией uWSGI или настройками Django?