Настроить Nginx для обслуживания внешнего интерфейса Angular, внутреннего интерфейса Django Rest Framework на одном сервере?

Интерфейс моего сайта построен на Angular 7, а серверная часть построена на Django Rest Framework. Все это работает через docker-compose, и я пытаюсь обслуживать весь сайт через NGINX.

Основная предпосылка моей конфигурации такова:

  • Если запрос включает URL-адрес с /api/ или /admin/, разрешите gunicorn обрабатывать запрос.
  • Если URL-адрес другой, отправьте его в корневой index.html, чтобы Angular мог обработать маршрутизацию.
  • Корневой URL-адрес / должен обслуживать мой предварительно скомпилированный javascript через index.html.

Со следующей конфигурацией 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;
    }

}

Эта конфигурация работает для моего приложения... У меня были другие проблемы, с которыми нужно было разобраться. Я обновил сообщение с моими URL-адресами от Django. Как видите, в этом проекте я не использую Django далеко за пределами API. Если ваш вариант использования более сложен, посмотрите ответ от @wmorrel

vitale232 04.06.2019 22:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
2 457
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваши конфиги говорят, что все, что доступно от /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 — «Не найдено». Есть идеи?

vitale232 28.05.2019 11:31

Я не могу помочь, не увидев больше проекта. Вы уверены, что ваш метод авторизации сохраняется? Используете ли вы файлы cookie, токены доступа к заголовку или что-то еще; и правильно ли они устанавливаются? Похоже, ваши проблемы глубже, чем просто конфигурация прокси.

wmorrell 29.05.2019 17:51

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 не делает этого?

vitale232 31.05.2019 17:18

Нет, исходная конфигурация будет использовать прокси только в том случае, если путь соответствует регулярному выражению api|admin. Если вы обслуживаете какие-либо пути из приложения Django, которые соответствуют нет, то исходная конфигурация попытается загрузиться из /usr/src/app/staticfiles/, а если не будет найдена, вместо этого вернет index.html. Кроме того, если у вас есть совпадающие файлы Angular, эта конфигурация попытается вместо этого загрузиться из Django.

wmorrell 03.06.2019 21:57

Я принял это как ответ. Ваш первый абзац относится к моим реальным проблемам, и ваша обновленная конфигурация, вероятно, будет полезна для проектов, которые используют Django более интенсивно, чем я. Однако есть одна проблема с вашей конфигурацией... Это не позволяет маршрутизации Angular работать правильно. Что-то вроде try_files $uri $uri/ $uri/index.html @upstream_proxy; действительно? Спасибо за вашу помощь.

vitale232 04.06.2019 22:27

У меня только поверхностное знакомство с Angular, так что ymmv. Если проблема связана именно с загрузкой index.html в качестве запасного варианта для пустого пути, я бы просто добавил блок местоположения для пустого пути, указывающего на index.html. Я подозреваю, что происходит нечто большее, поэтому более надежным решением было бы настроить все элементы DRF для ответа на определенный путь, который не будет конфликтовать с Angular. Это сохраняет исходный try_files и указывает только на прокси-сервер для пути DRF. Я обновлю ответ, указав, как это может выглядеть.

wmorrell 04.06.2019 22:41

Другие вопросы по теме