AngularJS和处理404错误

用AngularJS应用程序提供正确的404的最好方法是什么?

一点背景:我正在构build一个Angular应用程序,并select使用

$locationProvider.html5Mode(true); 

因为我希望URL看起来很自然(和多页面的“传统”Web应用程序无法区分)。

在服务器端(一个简单的Python Flask应用程序),我有一个捕获所有的处理程序,redirect到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目的)。

用Angular处理404的最好方法是什么? 我应该不用担心,坚持一个全面的? 或者我应该删除捕获所有,并在服务器端提供正确的404?

编辑清晰

我认为你是混淆Flask路线与Angular路线。

404错误代码是HTTP协议的一部分。 当所请求的URL不被服务器知道时,Web服务器将其用作对客户端的响应。 因为你在Flask服务器中join了一个全新的东西,你永远不会得到一个404,Flask将会调用你的视图函数来访问你在地址栏中input的任何URL。 在我看来,你不应该有一个全面的,只是让Flask响应404当用户在地址栏中键入一个无效的URL,没有什么不对。 Flask甚至允许您在返回404代码时发送自定义页面,以便您可以使错误页面看起来像您的网站的其余部分。

在Angular方面,实际上没有HTTP事务,因为应用程序内部的所有路由都发生在客户端,而不知道服务器。 这可能是你的困惑的一部分,Angular链接完全在客户端处理,即使在html5mode中也没有任何请求,所以在这种情况下没有404错误的概念,仅仅是因为没有服务器参与。 发送给未知路由的angular度链接将落入otherwise子句中。 这里要做的正确的事情是显示一个错误消息(如果用户需要知道这个条件,可以做些什么),或者忽略未知路由,就像redirectTo: '/'那样。

这似乎不是你的情况,但如果除了服务Angular应用程序,你的服务器实现了一个Angular在运行的时候可以使用的API,那么Angular可以从Flask得到一个404,如果它使用无效的url。 但是,如果发生这种情况,您不希望向用户显示404错误页面,因为请求是应用程序内部的,而不是由用户直接触发的。

我希望这有助于澄清情况!

在玩了一会之后,还有和米格尔的一些讨论,我编了几个不同的解决scheme:

  1. 只要使用一个全面的,不要担心适当的404。 这可以用服务器端代码来设置(比如在我的原始解决scheme中),或者更好的方法是在Web服务器上重写URL。
  2. 为您的angular度应用(如/app )保留您的网站的某个部分。 对于这个部分,build立一个全面的,不要担心适当的404。 您的其他页面将作为常规页面提供,并访问任何不以/app开头的无效URL将导致正确的404。
  3. 不断确保app.js中的所有路由都在您的服务器端代码中进行镜像(是的,非常烦人),在那里您将拥有这些路由来提供您的angular度应用程序。 所有其他路线将404。

PS第二个选项是我个人最喜欢的。 我已经试过了,效果很好。

这是一个古老的线索,但我寻找答案时,它凸显了它。

添加到你的appRoutes.js的结尾,并做一个404.html的观点。

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

我认为,如果您没有为您的网站的真实网页提供可用的非JavaScript内容,那么真正的http 404将会变得毫无用处。 search索引器不太可能能够呈现您的angular度网站索引。

如果您担心search引擎优化,您将需要某种服务器端的方式来渲染angular色页面呈现的内容。 如果你有这个问题,为无效URL添加404是最容易的部分。

这是处理错误的最佳方法,并且很好地工作

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