Интерфейс моего сайта построен на Angular 7, а серверная часть построена на Django Rest Framework. Все это работает через docker-compose, и я пытаюсь обслуживать весь сайт через NGINX.
Основная предпосылка моей конфигурации такова:
Со следующей конфигурацией Nginx я могу посетить все маршруты Angular. Я могу посетить страницу администратора и мой доступный для просмотра API. Однако, когда я перехожу к /admin или доступному для просмотра API, все статические файлы возвращают ошибку 404.
Вы видите проблему? Спасибо!
# urls.py
urlpatterns = [
re_path(r'^favicon\.ico$', favicon_view),
path('api/v1/', include('api.urls'), name='api'),
path('admin/', admin.site.urls),
]
# nginx.conf
upstream my_app {
server django:8000;
}
server {
listen 80;
location /staticfiles/ {
alias /usr/src/app/staticfiles/;
}
location ~ (api|admin) {
proxy_pass http://my_app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location / {
root /usr/src/app/staticfiles/;
try_files $uri $uri/ /index.html;
}
}
Ваши конфиги говорят, что все, что доступно от /api/
или /admin/
, предоставляется прокси для my_app
. Таким образом, вы можете либо убедиться, что статические файлы, используемые этими конечными точками, доступны через Django Rest Framework, ИЛИ указать NGINX всегда сначала проверять статические файлы, а затем возвращаться к прокси-серверу my_app
.
Первый вариант будет включать настройку STATIC_ROOT
, STATIC_URL
, STATICFILES_STORAGE
и т. д. в соответствии с Документация Django по статическим файлам (ссылка ведет на текущую версию для разработчиков).
Другой вариант включает в себя сбор ресурсов, используемых /api/
и /admin/
, в том же месте, что и ваши ресурсы Angular, и изменение конфигурации NGINX, чтобы она выглядела примерно так:
# nginx.conf
upstream my_app {
server django:8000;
}
server {
listen 80;
location /staticfiles/ {
alias /usr/src/app/staticfiles/;
}
location / {
root /usr/src/app/staticfiles/;
try_files $uri $uri/ index.html;
location /drf {
proxy_pass http://my_app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
}
По сути, это говорит о том, что попробуйте найти все в вашем каталоге Angular staticfiles
, если он не найден, попробуйте найти его в своем приложении DRF.
Спасибо за ответ. Я пытался вставить ваш nginx.conf
, и это не совсем правильно. Я могу перейти к доступному для просмотра API, как и ожидалось (например, /api/v1/users/
). Когда я захожу в /admin/
, я получаю 403 — Запрещено. Когда я захожу в http://localhost:1337/admin/login/?next=/admin/
, это работает. Когда я вхожу в систему и перенаправляюсь на /admin/
, я получаю 403. Что касается маршрутов Angular, если я перехожу к корневому URL-адресу (http://localhost:1337/
), он работает нормально. Нажатие кнопок в приложении продолжает навигацию в порядке. Однако прямой переход к одному из URL-адресов Angular (например, /about/
) приводит к ошибке 404 — «Не найдено». Есть идеи?
Я не могу помочь, не увидев больше проекта. Вы уверены, что ваш метод авторизации сохраняется? Используете ли вы файлы cookie, токены доступа к заголовку или что-то еще; и правильно ли они устанавливаются? Похоже, ваши проблемы глубже, чем просто конфигурация прокси.
FWIW, я использую токены доступа к заголовку для аутентификации. Кажется, он работает правильно. Я внес некоторые изменения в обработку статических файлов в Django (а именно, начал размещать статические файлы на AWS S3), что означало переработку моих статических настроек в Django, и теперь все работает, как и ожидалось. ВОПРОС: В вашем первом абзаце ответа OR tell NGINX to always try the static files first, then fall back to the my_app proxy.
- Разве мой оригинальный nginx.conf не делает этого?
Нет, исходная конфигурация будет использовать прокси только в том случае, если путь соответствует регулярному выражению api|admin
. Если вы обслуживаете какие-либо пути из приложения Django, которые соответствуют нет, то исходная конфигурация попытается загрузиться из /usr/src/app/staticfiles/
, а если не будет найдена, вместо этого вернет index.html
. Кроме того, если у вас есть совпадающие файлы Angular, эта конфигурация попытается вместо этого загрузиться из Django.
Я принял это как ответ. Ваш первый абзац относится к моим реальным проблемам, и ваша обновленная конфигурация, вероятно, будет полезна для проектов, которые используют Django более интенсивно, чем я. Однако есть одна проблема с вашей конфигурацией... Это не позволяет маршрутизации Angular работать правильно. Что-то вроде try_files $uri $uri/ $uri/index.html @upstream_proxy;
действительно? Спасибо за вашу помощь.
У меня только поверхностное знакомство с Angular, так что ymmv. Если проблема связана именно с загрузкой index.html
в качестве запасного варианта для пустого пути, я бы просто добавил блок местоположения для пустого пути, указывающего на index.html
. Я подозреваю, что происходит нечто большее, поэтому более надежным решением было бы настроить все элементы DRF для ответа на определенный путь, который не будет конфликтовать с Angular. Это сохраняет исходный try_files
и указывает только на прокси-сервер для пути DRF. Я обновлю ответ, указав, как это может выглядеть.
Эта конфигурация работает для моего приложения... У меня были другие проблемы, с которыми нужно было разобраться. Я обновил сообщение с моими URL-адресами от Django. Как видите, в этом проекте я не использую Django далеко за пределами API. Если ваш вариант использования более сложен, посмотрите ответ от @wmorrel