AngularJS + Django: обновление URL или прямой доступ не загружается правильно

У нас есть приложение AngularJS, встроенное в наше приложение Django, с маршрутизацией URL, обработанной AngularJS ui-router. Все работает нормально, перемещаясь между частицами с помощью ui-sref и щелкая в приложении.

return $stateProvider.state('root.dashboard', {
        abstract: true,
        url: 'dashboard/'
      }).state('root.dashboard.profile', {
        url: 'profile/',
        views: {
          '@': {
            templateUrl: Urls['dashboard:profile'](),
            controller: 'ProfileController'
          }
        }
      }).state('root.dashboard.home', {
        url: '',
        views: {
          '@': {
            templateUrl: Urls['dashboard:dashboard_home'](),
            controller: 'DashboardController'
          }
        }
...

Проблема заключается в том, что пользователь перешел на страницу без полномочий root (например, http://example.com/dashboard/profile/), и пользователь обновляет браузер, повторно загружает URL-адрес браузера или просто вставляет URL-адрес без корня непосредственно в браузера. В этом случае вместо загрузки страницы, сохраняющей тот же URL-адрес в браузере, пользователь перенаправляется на корневую страницу (http://example.com/dashboard/).

Поскольку маршрутизация выполняется с помощью Angular, на стороне сервера у нас нет URL-адресов, определенных для тех URL-адресов, которые не являются корневыми; вместо этого у нас есть промежуточное программное обеспечение, которое перенаправляет 404s на корневую страницу:

class Redirect404(object):
    def process_response(self, request, response):
        if response.status_code != 404 or request.method != 'GET':
            return response
        return HttpResponsePermanentRedirect('/dashboard')

Мы ожидаем, что маршрутизатор сможет поддерживать исходный URL-адрес и вернуть пользователя на исходную страницу (т.е. "dashboard/profile" ). Обратите внимание, что мы установили HTML5Mode в Angular следующим образом:

$locationProvider.html5Mode = true;

Есть некоторая ошибка в нашем понимании и/или настройке, и я хотел бы получить разъяснения.

Ответы

Ответ 1

Мы ожидаем, что маршрутизатор сможет поддерживать исходный URL-адрес и возвращать пользователя на исходную страницу.

Это недоразумение.

Вот последовательность событий:

  • Пользователь вводит http://example.com/dashboard/profile/ в строку местоположения.
  • Браузер отправляет запрос GET на сервер для этого URL-адреса.
  • Ваш сервер отвечает с ответом 301 с перенаправлением.
  • Браузер видит ответ и отправляет новый запрос GET на http://example.com/dashboard/.
  • Сервер отвечает вашей страницей Angular.
  • Приложение Angular запустится и просмотрит window.href, чтобы узнать, что такое текущий маршрут. Он видит корневой маршрут и отвечает соответствующим образом.

Другими словами, при перенаправлении вы теряете исходный URL.

Решение прост: вместо перенаправления просто верните свою страницу в ответ на любой (действительный) URL-адрес. Таким образом, запрошенный URL-адрес поддерживается, и когда Angular запускается, он сможет определить правильный маршрут. (Предполагается, что маршрутизация настроена правильно в Angular, но похоже, что вы работаете.)

Реализация также проста. Просто измените Django urls.py на что-то вроде этого:

urlpatterns = [
    url(r'^dashboard/$', my_view),
]

примерно так:

urlpatterns = [
    url(r'^dashboard/.*$', my_view),
]