使用AngularJS应用程序提供正确404的最佳方法是什么?
一点背景:我正在构建一个Angular应用并选择使用
$locationProvider.html5Mode(true);
因为我希望网址显得自然(与多页“传统”网络应用无法区分)。
在服务器端(一个简单的Python Flask应用程序),我有一个全能的处理程序,可以将所有内容重定向到角度应用程序:
@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状态代码(主要用于搜索引擎优化目的)。
使用Angular处理404s的最佳方法是什么?我不应该担心它并坚持一个全能的?或者我应该删除全部服务器并在服务器端提供正确的404?
为了清晰起见而编辑
答案 0 :(得分:32)
我认为你将Flask路线与Angular路线混淆。
404错误代码是HTTP协议的一部分。当服务器不知道请求的URL时,Web服务器将其用作对客户端的响应。因为你在Flask服务器中放置了一个全能型,所以你永远不会获得404,Flask会为你在地址栏中输入的任何URL调用你的视图功能。在我看来,当用户在地址栏中键入无效的URL时,你不应该有一个全能,只是让Flask回复404,这没有任何问题。 Flask甚至允许您在返回404代码时发送自定义页面,因此您可以使错误页面看起来与您网站的其余部分一样。
在Angular方面,实际上没有HTTP事务,因为应用程序内部的所有路由都发生在客户端,而服务器甚至不知道。这可能是您混淆的一部分,Angular链接完全在客户端处理,即使在html5mode中也没有向服务器发出任何请求,因此在此上下文中没有404错误的概念,因为没有服务器参与。将您发送到未知路由的Angular链接将属于otherwise
子句。这里要做的正确的事情是要么显示错误消息(如果用户需要了解这个条件并且可以对此做些什么),要么忽略未知路由,就像redirectTo: '/'
那样。
这似乎不是你的情况,但如果除了服务Angular应用程序之外,你的服务器还实现了Angular在运行时可以使用的API,那么如果Angular向它发出异步请求,那么Angular可以从Flask获得404使用无效网址的API。但如果发生这种情况,您不希望向用户显示404错误页面,因为该请求是应用程序内部的,而不是由用户直接触发。
我希望这有助于澄清情况!
答案 1 :(得分:17)
在玩了一下之后,以及与Miguel的一些讨论,我编写了一些不同的解决方案:
/app
)。对于本节,设置一个全能,不要担心正确的404。您的其他网页将作为常规网页投放,并且访问不以/app
开头的任何无效网址将导致正确的404。P.S。第二种选择是我个人的最爱。我已经尝试过了,效果很好。
答案 2 :(得分:2)
这是一个旧帖子,但我在寻找答案的过程中突然看到它。
将此添加到appRoutes.js的末尾并制作404.html视图。
.when('/404', {
templateUrl: 'views/404.html',
controller: 'MainController'
})
.otherwise({ redirectTo: '/404' })
答案 3 :(得分:0)
如果您没有为网站的真实网页提供可用的非JavaScript内容,我认为真正的http 404对于SEO目的而言将毫无用处。搜索索引器不太可能呈现您的角度站点以进行索引。
如果您担心SEO,则需要某种服务器端方式来呈现角度页面呈现的内容。如果您有,那么为无效网址添加404是最容易解决的问题。
答案 4 :(得分:-2)
这是处理错误并且效果很好的最佳方法
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'
})
......
};