16

sto usando $ routeProvider e $ locationProvider per gestire URL pushState in una singola pagina app (SPA), qualcosa di simile:Come faccio butto un vero e proprio 404 o 301 con un URL pushState angolare

angular.module('pets', []) 

    .config(function($routeProvider, $locationProvider) { 
    $locationProvider.html5Mode(true); 
    $routeProvider.when('/pet/:petId', { 
     controller: 'petController' 
    }); 
    }) 

    .controller('petController', function($scope, petService, $routeParams){ 
    petService.get('/api/pets/' + $routeParams.petId).success(function(data) { 
     $scope.pet = data; 
    }); 
    }); 

L'URL viene utilizzato per estrarre il contenuto dal server che può o non può esistere.

Se si trattava di un sito Web a più pagine ordinario, una richiesta di contenuto mancante avrebbe attivato una risposta dell'header 404 dal server e una richiesta di contenuto spostato avrebbe attivato un 301. Ciò avviserebbe Google del contenuto mancante o spostato.

diciamo per esempio mi ha colpito un URL simile a questo:

http://example.com/pet/123456

e dire non c'è tale animale domestico nel database, come può il mio SPA restituire un 404 su quel contenuto.

In caso contrario, esiste un altro modo per avvisare correttamente l'utente o il motore di ricerca che l'URL richiesto non esiste? C'è qualche altra soluzione che non sto considerando?

+0

Se il server restituisce un codice di stato esterno all'intervallo 200, la chiamata 'get' deve essere rifiutata e passata al callback' error': '.success (cb) .error (cb)'. È quello che stai cercando? –

+0

@DavinTryon - non proprio, posso prendere il 404 dalla richiesta AJAX senza problemi, la domanda è cosa fare con esso allora. In un'applicazione multi-pagina restituirei un codice di stato 404 nell'intestazione della risposta. Ovviamente non posso farlo in una SPA. Per un utente posso semplicemente rendere un bel testo 404, ma come faccio ad avvisare un crawler che la pagina non è lì. – superluminary

+0

Immagino che la domanda possa essere estesa a qualsiasi chiamata AJAX? In altre parole, come indicare a un crawler che una chiamata AJAX (che restituisce il contenuto da renderizzare) restituisce un 404? –

risposta

4

La vera domanda è non http://example.com/pet/123456 ritorno niente?

Se il punto di partenza è http://example.com/ e c'è un link per http://example.com/pet/123456 poi angolare chiamerà il petController che a sua volta fa una chiamata AJAX per http://example.com/api/pet/123456.

Un crawler non lo farebbe, ma invece proverebbe a chiamare direttamente http://example.com/pet/123456.

Quindi il tuo server deve essere in grado di gestire quella chiamata. Se non esiste un animale domestico con l'id 123456 allora dovrebbe restituire 404. Problema risolto. Se c'è allora dovrebbe restituire la SPA. L'applicazione dovrebbe quindi gestire la situazione di conseguenza.

+1

Questo funziona correttamente quando si colpisce direttamente l'URL, ma quando lo si colpisce tramite pushstate, verrà effettuata solo la chiamata API. La SPA è già stata caricata. – superluminary

+0

Ah, no, hai ragione. Il crawler colpirà direttamente l'URL. Spetta quindi al server restituire la SPA o un'intestazione 404. – superluminary

+1

Finalmente una risposta corretta e corretta! Vorrei solo aggiungere questo, se ad es. si dispone di un'architettura in cui il front end è servito da un server diverso dall'API, non è così banale distinguere quando restituire 404. Ovviamente, Angular non può farlo, poiché funziona in un browser. Pertanto, hai 3 opzioni: 1. assicurati di non avere affatto 404 2. ignorali e reindirizza l'utente ad es. front page 3. utilizzare un modo per eseguire il prerender delle pagine (ad es. prerender.io ha un meccanismo appropriato per 404s: https://prerender.io/documentation/best-practices). Vale la pena notare che solo la terza opzione è SEO-friendly. –

0

Prova questa

angular.module('pets', []) 
 

 
    .config(function($routeProvider, $locationProvider) { 
 
    $locationProvider.html5Mode(true); 
 
    $routeProvider.when('/pet/:petId', { 
 
     controller: 'petController' 
 
    }). otherwise({ yourUrl:'/404.html'}) // Render 404 view; 
 
    })

+0

Bello, ma cosa succede se http://api.example.com/pets/123456 non restituisce una risorsa? – superluminary

+0

Davvero non penso che funzionerà. Il router corrisponderà al primo modello indipendentemente dal fatto che la successiva chiamata ajax abbia esito positivo. La callback ajax verrà eseguita molto tempo dopo il completamento del router. – superluminary

+0

L'unico meccanismo concepibile qui sarebbe quello di fare una richiesta sincrona nel router. – superluminary

3

In base a questa risposta How do search engines deal with AngularJS applications?, è necessario utilizzare Browser senza testa per elaborare le richieste di crawler e restituire istantanee della pagina con il codice di risposta appropriato. https://developers.google.com/webmasters/ajax-crawling/docs/html-snapshot

L'esempio di google non ha incluso 301.302 o 404 casi. Tuttavia, il loro codice potrebbe essere modificato per analizzare il contenuto dell'istantanea e modificare il codice di risposta.

Ho trovato prerender.io offre questo servizio, ma non è gratuito. Tuttavia, hanno un piano gratuito se hai meno di 250 pagine. Il Prerender chiede che in caso di 404 o 301, si aggiunge un meta tag al DOM.

questo metatag viene quindi rilevato dal browser headless e il codice di risposta viene modificato.

+1

Queste informazioni sono state ufficialmente ritirate da Google. Sono crawler in grado di eseguire la scansione di pagine senza dover utilizzare una soluzione browser headless. – Failpunk

+0

@Failpunk grazie! questa è certamente una buona notizia per i siti Web di SinglePage là fuori :) –

+0

@Failpunk: rimuovere il supporto pre-rendering per il tuo sito sarebbe un errore dato che ci sono più bot oltre a Google stessa. – diosney