39

用AngularJS应用程序提供正确404的最佳方式是什么?AngularJS和处理404错误

一点背景:我要建一个角度应用程序,并选择使用

$locationProvider.html5Mode(true); 

,因为我想要的网址出现自然(和无法区分多页的“传统”的Web应用程序)。

在服务器端(一个简单的Python应用程序瓶),我有一个重定向一切角应用一个包罗万象的处理程序:

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

现在,我试图找出该怎么做404错误。大多数我见过做以下的角的应用程序:

.otherwise({ redirectTo: '/' }) 

这意味着,有没有办法,他们可以成为一个适当的404

不过,我宁愿回到正确的404,与404状态代码(主要用于SEO目的)。

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

编辑为清楚起见

+0

要在404你可以提到你的使用情况怎样做 –

+0

当一个访问/ ASDF,应该采取一个404页:“对不起,你要访问的页面不存在” 。应该返回404状态码。 – Ryan

+0

你可以注册一个响应拦截器,并检查拦截器中的状态代码,你可以在http状态代码中找到404,你可以使用$ location.path('path')重定向到任何路径。 –

回答

17

玩弄了一下,以及与米格尔一些讨论后,我整理了几个不同的解决方案:

  1. 只需使用一个包罗万象的,不要担心适当的404的。这可以通过服务器端代码(如我的原始解决方案)来设置,或者更好,在您的Web服务器上重新写入URL。
  2. 为您的角度应用保留您网站的某个部分(如/app)。对于本节,设置一个全面的,不要担心适当的404。您的其他页面将作为常规页面提供,并访问任何不以/app开头的无效网址将导致404错误。
  3. 连续确保app.js中的所有路由都在您的服务器端镜像 - (是的,非常讨厌),你将有这些路线提供你的角度应用程序。所有其他路线将为404.

P.S.第二个选项是我个人的最爱。我已经试过了,它工作得很好。

+0

我正遇到类似的问题,使用angular/node.js堆栈。我有一条使用特定ID进行数据查找的路线。对于一个好的URL,这可以正常工作。对于一个不好的网址,我只是用一个看起来破损的网页结束。这些网址看起来像:/ details/goodID vs. details/badID(我也注意到某些机器人喜欢尝试/ details/details/goodID,这也是一个糟糕的路线:/)。解决方案#2并没有真正处理这种情况,如果可能的话,我想避免#3。你遇到过其他想法吗?是否有404-ish的方式来报告错误客户端? – user3233032

+0

@Ryan - 关于#3,需要通过browserify具有所有定义的路由模块并不是那么糟糕吗?无论如何,我就是这么做的。 – aaaaaa

+0

@瑞恩原谅我,但没有这个服务器通话否定客户端SPA的全部点?我们称SPA为一次,然后通过Ajax使用Api。如果你必须去你的服务器的每个端点,那么为什么不简单地使用客户端/服务器模型? –

30

我想你混淆了瓶路线与角路线。

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

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

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

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

+0

我将删除catch-all,因为我希望能够提供适当的404错误(对于SEO等)。但是,现在我必须保留Flask传递给Angular的路由列表。这意味着,无论何时添加新路线,我都需要将其添加到我的app.js和我的controllers.py中。但说实话,我只想说一点事实。我怎么能更新一个位置的路线,并让它们在JS和Python代码中自动反映?我正在考虑用这些路由创建一个JSON文件(python会导入这些路由并在JSON文件被触摸时生成一个新的app.js)。 – Ryan

+0

你仍然困惑着服务器和客户端。您的Flask应用程序只有一个路径,''/“'将Angular应用程序提供给客户端。而已。 Angular应用程序可以根据需要定义多条路线,但这些是客户端,Flask服务器不涉及这些路线。事实上,通过如此简单的设置,我不清楚为什么你需要服务器上的Flask,看起来你只是为Angular应用程序提供静态文件。 – Miguel

+11

@Miguel我不会混淆他们。考虑一下:我在角度路由中使用了“/”和“/ about”的角度应用。我也启用了html5Mode。这意味着,如果用户转到“/”,则会向服务器发送请求,然后角度应用程序将启动。当用户导航到“/ about”时,请求将不会发送到服务器,因为角度应用程序现在正在处理它。但是,如果用户刷新页面,“/ about”将被发送到服务器。这意味着,需要在服务器上有一个“/ about”端点将请求传递到角度。 – Ryan

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

     ...... 

    }; 
+2

我没有downvote - 但我知道SO更喜欢不严格代码的答案。只是一个建议,因为我很感谢大多数花时间回答他人问题的人。 – aaaaaa

+0

它没有解决问题... –

0

我认为,一个真正的HTTP 404将是相当无用的“搜索引擎优化的目的,”如果你没有服务可用非-javascript内容为您的网站的真实网页。搜索索引器不太可能能够呈现您的角度网站进行索引。

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

2

这是一个古老的线程,但我在搜索答案时找到它。

将此添加到appRoutes.js的最后并创建一个404.html视图。

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

.otherwise({ redirectTo: '/404' })