AngularJS et traitement des erreurs 404

Quelle est la meilleure façon de servir des 404 avec une application AngularJS?

un petit fond: je suis en train de construire une application angulaire et j'ai choisi d'utiliser

$locationProvider.html5Mode(true);

parce que je veux que les URLs apparaissent naturel (et indistinguible d'une multi-page "traditionnel" application web).

du côté du serveur (une simple application Flask de Python), j'ai un gestionnaire catch-all qui redirige tout vers l'application angulaire:

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

Maintenant, j'essaie de comprendre que faire avec 404 erreurs. La plupart des applications angulaires que j'ai vues font ce qui suit:

.otherwise({ redirectTo: '/' })

ce qui signifie qu'il n'y a aucun moyen qu'ils peuvent servir un bon 404.

cependant, je préférerais retourner un 404 approprié, avec un code de statut 404 (principalement pour les besoins du référencement).

Quelle est la meilleure façon de traiter les 404s avec Angular? Ne devrais-je pas m'en inquiéter et rester avec un piège? Ou devrais - je supprimer le catch-all et servir des 404 sur le serveur côté?

édité pour plus de clarté

40
demandé sur Ryan 2013-07-08 08:44:57

5 réponses

je pense que vous confondez les routes en fiole avec les routes angulaires.

le code d'erreur 404 fait partie du protocole HTTP. Un serveur web l'utilise comme réponse à un client lorsque l'URL demandée n'est pas connue du serveur. Parce que vous mettez un catch-all dans votre Flask server vous n'obtiendrez jamais un 404, Flask invoquera votre fonction de vue pour N'importe quelles URLs que vous dactylographiez dans la barre d'adresse. À mon avis, vous ne devriez pas avoir un fourre-tout et laissez Flacon de répondre avec 404 lorsque l'utilisateur tape une URL invalide dans la barre d'adresse, il n'y a rien de mal à cela. Flacon vous permet même d'envoyer une page personnalisée lorsqu'un code 404 est retourné, de sorte que vous pouvez faire de la page d'erreur ressembler le reste de votre site.

du côté angulaire, il n'y a vraiment pas de transaction HTTP car tout le routage interne à l'application se produit dans le client sans que le serveur ne le sache. Cela peut être une partie de votre confusion, liens angulaires sont traitées entièrement dans le client sans aucune demande faite à le serveur même en html5mode, il n'y a donc pas de concept d'erreur 404 dans ce contexte, simplement parce qu'il n'y a pas d'implication du serveur. Un lien angulaire qui vous envoie à une route inconnue tombera tout simplement dans le otherwise l'article. La bonne chose à faire ici est d'afficher un message d'erreur (si l'utilisateur a besoin de savoir sur cette condition et peut faire quelque chose) ou tout simplement ignorer la route inconnue, comme l' redirectTo: '/' ne.

Cela ne semble pas être votre cas, mais si en plus de servir L'application angulaire votre serveur a implémenté une API que Angular peut utiliser pendant qu'elle tourne, puis Angular pourrait obtenir un 404 de Flask si elle a fait une requête asynchrone à cette API en utilisant une URL invalide. Mais vous ne voudriez pas montrer une page d'erreur 404 à l'utilisateur si cela se produisait, puisque la requête était interne à l'application et non déclenchée directement par l'utilisateur.

j'espère que cela aidera à clarifier la situation!

31
répondu Miguel 2013-07-08 07:53:05

Après avoir joué un peu, ainsi que quelques discussions avec Miguel, j'ai compilé quelques solutions:

  1. il suffit d'utiliser un catch-all et ne vous inquiétez pas sur les 404 appropriés. Cela peut être configuré avec du code côté serveur (comme dans ma solution originale), ou mieux, avec une réécriture D'URL sur votre serveur web.
  2. réserver une certaine section de votre site pour votre application angulaire (comme /app). Pour cette section, mettez en place un catch-all et ne vous inquiétez pas sur les 404. Votre les autres pages seront servies comme des pages régulières et visitant toute URL invalide qui ne commence pas par /app résultera en un 404 correct.
  3. assurez-vous en permanence que toutes vos routes dans app.js sont reflétés dans votre code côté serveur (Oui, assez ennuyeux), où vous aurez ces routes servir votre application angulaire. Toutes les autres routes seront 404.

P. S. La deuxième option est mon favori personnel. Je l'ai essayé et il fonctionne très bien.

17
répondu Ryan 2014-03-11 18:49:55

c'est un vieux fil, mais je l'ai traversé en cherchant la réponse.

ajoutez ceci à la fin de vos appRoutes.js et fais un 404.en mode html.

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

.otherwise({ redirectTo: '/404' })
2
répondu Russ 2016-11-18 05:38:20

je pense qu'un vrai http 404 va être assez inutile "pour des fins de référencement" si vous ne servez pas de contenu Non-javascript utilisable pour des pages réelles de votre site. Il est peu probable qu'un indexeur de recherche puisse rendre votre site angulaire pour l'indexation.

si vous êtes inquiet au sujet de SEO, vous aurez besoin d'une sorte de côté serveur pour rendre le contenu que vos pages angulaires rendent. Si vous avez cela, ajouter 404s pour les URLs invalides est la partie la plus facile du problème.

0
répondu rjmunro 2016-07-21 17:28:52

Voici la meilleure façon de gérer l'erreur et fonctionne bien

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'
        })

        ......

   };
-2
répondu Mike Jones 2014-03-08 14:51:14