Подтвердить что ты не робот

УгловыеJS и обращение с ошибками 404

Каков наилучший способ подачи правильного 404 с помощью приложения AngularJS?

Небольшой фон: я создаю приложение Angular и решил использовать

$locationProvider.html5Mode(true);

потому что я хочу, чтобы URL-адреса отображались естественными (и неотличимы от многостраничного "традиционного" веб-приложения).

На стороне сервера (простое приложение Python Flask) у меня есть обработчик catch-all, который перенаправляет все на Angular приложение:

@app.route('/', defaults={'path': ''})
@app.route('/<path>')
def index(path):
    return make_response(open('Ang/templates/index.html').read())

Теперь я пытаюсь выяснить, что делать с 404 ошибками. Большинство приложений Angular, которые я видел, делают следующее:

.otherwise({ redirectTo: '/' })

что означает, что они не могут служить правильному 404.

Тем не менее, я бы скорее вернул правильный 404 с кодом статуса 404 (в основном для целей SEO).

Каков наилучший способ обработки 404 с Angular? Должен ли я не беспокоиться об этом и придерживаться уловки? Или я должен удалить уловку и обслуживать 404 со стороны сервера?

отредактирован для ясности

4b9b3361

Ответ 1

Немного поиграв, а также некоторые обсуждения с Мигелем, я составил несколько разных решений:

  • Просто используйте catch-all и не беспокойтесь о правильных 404-х. Это можно настроить с помощью кода на стороне сервера (например, в моем исходном решении) или, лучше, с повторной записью URL-адресов на вашем веб-сервере.
  • Зарезервируйте определенный раздел своего сайта для своего приложения angular (например, /app). Для этого раздела создайте уловку и не беспокойтесь о правильных 404-х. Ваши другие страницы будут обслуживаться как обычные страницы, а посещение любого неверного URL-адреса, который не начинается с /app, приведет к правильному 404.
  • Непрерывно убедитесь, что все ваши маршруты в app.js зеркалированы в вашем серверном коде (да, довольно раздражает), где вы будете использовать эти маршруты в своем приложении angular. Все остальные маршруты будут 404.

P.S. Второй вариант - мой личный фаворит. Я пробовал это, и он работает хорошо.

Ответ 2

Я думаю, вы путаете маршруты Flask с маршрутами Angular.

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

На стороне Angular действительно нет HTTP-транзакции, потому что вся внутренняя маршрутизация приложения происходит на клиенте, даже если сервер не знает. Это может быть частью вашей путаницы, ссылки Angular обрабатываются целиком на клиенте без каких-либо запросов на сервер даже в html5mode, поэтому в этом контексте нет понятия ошибки 404, просто потому, что нет участия сервера. Ссылка Angular, которая отправляет вас на неизвестный маршрут, просто попадает в предложение otherwise. Для этого нужно либо показать сообщение об ошибке (если пользователь должен знать об этом состоянии и что-то сделать с ним), либо просто игнорировать неизвестный маршрут, как это делает redirectTo: '/'.

Это не похоже на ваш случай, но если помимо обслуживания приложения Angular на вашем сервере реализован API, который Angular может использовать во время его запуска, то Angular может получить 404 из Flask, если он сделал асинхронный запрос к этому API с использованием недопустимого URL-адреса. Но вы не захотите показывать страницу ошибки 404 пользователю, если это произошло, поскольку запрос был внутренним для приложения и не вызван пользователем напрямую.

Надеюсь, это поможет прояснить ситуацию!

Ответ 3

Это старый поток, но я смотрю на него во время поиска ответа.

Добавьте это в конец вашего appRoutes.js и сделайте представление 404.html.

.when('/404', {
    templateUrl: 'views/404.html',
    controller: 'MainController'
})

.otherwise({ redirectTo: '/404' })

Ответ 4

Я думаю, что настоящий http 404 будет очень бесполезным "для целей SEO", если вы не используете полезный контент без javascript для реальных страниц вашего сайта. Поисковый индексатор вряд ли сможет отобразить ваш сайт angular для индексирования.

Если вы беспокоитесь о SEO, вам понадобится какой-то серверный способ визуализации содержимого, которое будут отображаться ваши страницы angular. Если у вас есть это, добавление 404s для недопустимых URL-адресов является самой легкой частью проблемы.

Ответ 5

Вот лучший способ справиться с ошибкой и прекрасно работать

function ($routeProvider, $locationProvider, $httpProvider) {
    var interceptor = [
        '$rootScope', '$q', function (scope, $q) {

            function success(response) {
                return response;
            }

            function error(response) {
                var status = response.status;

                if (status == 401) {
                    var deferred = $q.defer();
                    var req = {
                        config: response.config,
                        deferred: deferred
                    };
                    window.location = "/";
                }

                if (status == 404) {
                    var deferred = $q.defer();
                    var req = {
                        config: response.config,
                        deferred: deferred
                    };
                    window.location = "#/404";
                }
                // otherwise
                //return $q.reject(response);
                window.location = "#/500";
            }

            return function (promise) {
                return promise.then(success, error);
            };

        }
    ];
    $httpProvider.responseInterceptors.push(interceptor);
});

// routes
app.config(function($routeProvider, $locationProvider) {
    $routeProvider
        .when('/404', {
            templateUrl: '/app/html/inserts/error404.html',
            controller: 'RouteCtrl'
        })
        .when('/500', {
            templateUrl: '/app/html/inserts/error404.html',
            controller: 'RouteCtrl'
        })

        ......

   };