Как мне выдать настоящую ошибку 404 или 301 с URL-адресом Angular pushstate

Я использую $routeProvider и $locationProvider для обработки URL-адресов pushstate в одностраничном приложении (SPA), примерно так:

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

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

Если бы это был обычный многостраничный веб-сайт, запрос отсутствующего контента вызвал бы ответ заголовка 404 от сервера, а запрос перемещенного контента вызвал бы 301. Это предупредило бы Google об отсутствующем или перемещенном контенте.

Скажем, например, я попал по такому URL-адресу:

http://example.com/pet/123456

и сказать, что в базе данных нет такого питомца, как мой SPA может вернуть 404 для этого контента.

В противном случае есть ли какой-либо другой способ правильно предупредить пользователя или поисковую систему о том, что запрошенный URL-адрес не существует? Есть ли какое-то другое решение, которое я не рассматриваю?


person superluminary    schedule 06.01.2015    source источник
comment
Если сервер возвращает код состояния за пределами диапазона 200, вызов get следует отклонить и передать обратному вызову error: .success(cb).error(cb). Это то, что вы ищете?   -  person Davin Tryon    schedule 06.01.2015
comment
@DavinTryon - не совсем, я могу поймать 404 из запроса AJAX без проблем, вопрос в том, что с этим делать потом. В многостраничном приложении я бы вернул код состояния 404 в заголовке ответа. Очевидно, я не могу сделать это в СПА. Для пользователя я могу просто отобразить красивый текст 404, но как предупредить сканер о том, что страницы нет.   -  person superluminary    schedule 06.01.2015
comment
Я предполагаю, что тогда вопрос можно было бы расширить до любого вызова AJAX? Другими словами, как указать сканеру, что вызов AJAX (который возвращает содержимое для рендеринга) возвращает ошибку 404?   -  person Davin Tryon    schedule 06.01.2015
comment
Я не думаю, что вы можете сделать это. Я пытался мыслить творчески. Один из возможных вариантов: если на сервере вы отслеживаете удаленные URL-адреса (возможно, в базе данных), вы можете вернуть 404, если URL-адрес запроса соответствует удаленному пути. Если бы он не был удален, вы бы вернули свою индексную страницу. Очевидно, что это будет работать только для внешних ссылок на ваш сайт.   -  person Wayne Ellery    schedule 06.01.2015


Ответы (3)


Реальный вопрос: возвращает ли http://example.com/pet/123456 что-нибудь вообще?

Если вашей отправной точкой является http://example.com/ и есть ссылка на http://example.com/pet/123456, тогда Angular вызовет petController, который, в свою очередь, вызовет AJAX http://example.com/api/pet/123456.

Искатель не стал бы этого делать, а вместо этого попытался бы вызвать http://example.com/pet/123456 напрямую.

Таким образом, ваш сервер должен быть в состоянии обработать этот вызов. Если питомца с идентификатором 123456 нет, то он должен вернуть 404. Проблема решена. Если есть, то он должен вернуть SPA. Затем приложение должно соответствующим образом обработать ситуацию.

person a better oliver    schedule 09.01.2015
comment
Это отлично работает при прямом переходе по URL-адресу, но при переходе через pushstate будет выполнен только вызов API. SPA уже загружен. - person superluminary; 09.01.2015
comment
Ах, нет, ты прав. Сканер напрямую попадет по URL-адресу. Затем сервер должен вернуть SPA или заголовок 404. - person superluminary; 09.01.2015
comment
Наконец-то правильный и правильный ответ! Я бы только добавил, что, если, например. у вас есть архитектура, в которой внешний интерфейс обслуживается сервером, отличным от API, не так уж и просто понять, когда возвращать 404. Очевидно, что Angular не может этого сделать, поскольку он работает в браузере. Таким образом, у вас есть 3 варианта: 1. убедиться, что ошибок 404 вообще нет 2. игнорировать их и перенаправить пользователя, например, на главная страница 3. используйте какой-либо способ предварительной обработки ваших страниц (например, у prerender.io есть правильный механизм для ошибок 404: prerender .io/documentation/best-practices). Стоит отметить, что только 3-й вариант оптимизирован для SEO. - person piotr.d; 20.08.2015
comment
Современный сканер будет выполнять JavaScript - person Toolkit; 15.12.2016
comment
@Toolkit Дело не в том, чтобы быть современным. И даже не все индексаторы самых популярных поисковых систем выполняют JavaScript. Не говоря уже о миллионах других сканеров. Это все равно, что сказать, что современные пользователи используют аппаратное обеспечение А или браузер Б. Это не так. Выполнение сценариев также не решает проблему, к которой я обращался: сервер должен возвращать соответствующий ответ на глубокие ссылки, несмотря ни на что. - person a better oliver; 26.12.2016

Согласно этому ответу Как поисковые системы работают с приложениями AngularJS? Вам следует использовать Headless Browser для обработки запросов поисковых роботов и предоставления снимков страницы с соответствующим кодом ответа. https://developers.google.com/webmasters/ajax-crawling/docs/html-snapshot

Пример Google не включал 301 302 или 404 случая. Однако их код можно модифицировать для анализа содержимого моментального снимка и изменения кода ответа.

Я обнаружил, что prerender.io предлагает эту услугу, но она платная. Однако у них есть бесплатный план, если у вас менее 250 страниц. Prerender просит, чтобы в случае 404 или 301 вы добавили метатег в DOM.

<meta name="prerender-status-code" content="404">

затем этот метатег обнаруживается их безголовым браузером, и код ответа изменяется.

person Roman Mik    schedule 07.07.2015
comment
Эта информация официально объявлена ​​устаревшей Google. Их краулер может сканировать страницы без использования безголового браузера. - person Justin; 06.01.2016
comment
@Failpunk, спасибо! это, безусловно, хорошая новость для одностраничных веб-сайтов :) - person Roman Mik; 07.01.2016
comment
@Failpunk: удаление поддержки предварительного рендеринга для вашего сайта было бы ошибкой, поскольку помимо самого Google ботов больше. - person Diosney; 20.01.2017

Попробуй это

angular.module('pets', [])

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

person Anamika    schedule 08.01.2015
comment
Я действительно не думаю, что это сработает. Маршрутизатор будет соответствовать первому шаблону независимо от того, будет ли успешным более поздний вызов ajax. Обратный вызов ajax будет выполняться еще долго после завершения работы маршрутизатора. - person superluminary; 09.01.2015
comment
Единственным мыслимым механизмом здесь было бы выполнение синхронного запроса в маршрутизаторе. - person superluminary; 09.01.2015