【问题标题】:AngularJS and Handling 404 ErrorsAngularJS 和处理 404 错误
【发布时间】:2013-07-05 08:28:45
【问题描述】:

使用 AngularJS 应用程序提供正确的 404 的最佳方式是什么?

一点背景知识:我正在构建一个 Angular 应用程序并选择使用

$locationProvider.html5Mode(true);

因为我希望 URL 看起来自然(并且与多页“传统”网络应用程序没有区别)。

在服务器端(一个简单的 Python Flask 应用程序),我有一个包罗万象的处理程序,可以将所有内容重定向到 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?

为清晰起见进行了编辑

【问题讨论】:

  • 你想在 404 上做什么,能不能提一下你的用例
  • 当访问/asdf时,应该被带到一个404页面:“对不起,你试图访问的页面不存在”。应该返回一个 404 状态码。
  • 您可以注册一个响应拦截器并检查拦截器中的状态代码,如果您在 http 状态代码中找到 404,您可以使用 $location.path('path') 重定向到任何路径

标签: javascript angularjs flask http-status-code-404 angularjs-routing


【解决方案1】:

这是一个旧线程,但我在寻找答案时遇到了它。

将此添加到您的 appRoutes.js 的末尾并创建一个 404.html 视图。

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

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

【讨论】:

    【解决方案2】:

    我认为,如果您没有为网站的真实页面提供可用的非 JavaScript 内容,那么“出于 SEO 目的”,真正的 http 404 将毫无用处。搜索索引器不太可能呈现您的 Angular 网站以进行索引。

    如果您担心 SEO,您将需要某种服务器端方式来呈现您的 Angular 页面正在呈现的内容。如果你有,为无效 URL 添加 404 是问题中最简单的部分。

    【讨论】:

      【解决方案3】:

      在玩了一会儿之后,以及与 Miguel 的一些讨论,我整理了一些不同的解决方案:

      1. 只需使用包罗万象的方法,不必担心正确的 404。这可以使用服务器端代码进行设置(就像我的原始解决方案一样),或者更好的是,在您的网络服务器上重写 URL。
      2. 为您的 Angular 应用程序保留您网站的某个部分(例如 /app)。对于本节,设置一个包罗万象的内容,不要担心正确的 404。您的其他页面将作为常规页面提供,访问任何不以 /app 开头的无效 URL 将导致正确的 404。
      3. 不断确保 app.js 中的所有路由都反映在服务器端代码中(是的,这很烦人),在那里您可以让这些路由为您的 Angular 应用程序提供服务。所有其他路线将 404。

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

      【讨论】:

      • 我遇到了与 angular / node.js 堆栈类似的问题。我有一条使用特定 ID 进行数据查找的路由。对于一个好的 URL,这很好用。对于一个糟糕的 URL,我只会看到一个看起来很糟糕的网页。 url 看起来像:/details/goodID 与 details/badID(我还注意到某些机器人喜欢尝试 /details/details/goodID,这也是一条糟糕的路线:/)。解决方案 #2 并不能真正处理这种情况,如果可能的话,我想避免 #3。你有没有遇到任何其他想法?是否有 404-ish 方式来报告错误客户端??
      • @Ryan - 关于#3,通过 browserify 需要一个包含所有定义的路由模块不是很糟糕吗?反正我就是这么干的。
      • @Ryan 请原谅我,但是这个服务器调用是否否定了客户端 SPA 的全部意义?我们调用一次 SPA 并从那里通过 Ajax 使用 Api。如果您必须为每个端点访问您的服务器,那么为什么不简单地使用客户端/服务器模型呢?
      【解决方案4】:

      这是处理错误的最佳方法,并且效果很好

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

      【讨论】:

      • 我没有投反对票 - 但我知道 SO 更喜欢不是严格代码的答案。只是一个建议,因为我感谢大多数花时间回答他人问题的人。
      • 这是“我如何拦截并处理 angularjs 中的所有 404 错误”问题的答案。我正在寻找这个但找不到它,我知道我正在寻找的是如何为所有 $http 调用添加一个拦截器,因为没有这个,angularjs 不会将 404 视为错误,就像另一个代码和它一样将在承诺中解决。我需要一种自动错误所有 404 的方法,以便我可以捕获它们,例如在登录失败时返回 404 的登录中。希望它可以帮助某人#angularjs #httpinterceptor #interceptor
      【解决方案5】:

      我认为您将 Flask 路由与 Angular 路由混淆了。

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

      在 Angular 方面,实际上没有 HTTP 事务,因为应用程序内部的所有路由都发生在客户端,而服务器甚至都不知道。这可能是您混淆的一部分,Angular 链接完全在客户端处理,即使在 html5 模式下也没有向服务器发出任何请求,因此在这种情况下没有 404 错误的概念,仅仅是因为没有服务器参与。将您发送到未知路线的 Angular 链接将落入otherwise 子句中。此处正确的做法是显示错误消息(如果用户需要了解此情况并可以对此采取措施)或只是忽略未知路线,就像 redirectTo: '/' 所做的那样。

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

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

      【讨论】:

      • 我将删除全部内容,因为我希望能够处理正确的 404 错误(对于 SEO 等)。但是,现在我必须保留 Flask 传递给 Angular 的路由列表。这意味着每当我添加一个新路由时,我都需要将它添加到我的 app.js 和我的 controllers.py 中。但老实说,我只想说实话。如何在一个位置更新路由并让它们在 JS 和 python 代码中自动反映?我正在考虑使用路由创建一个 JSON 文件(python 将导入路由,并且在触摸 JSON 文件时会生成一个新的 app.js)。
      • 你还在混淆服务器端和客户端。您的 Flask 应用程序只有一个路由,"/" 将 Angular 应用程序提供给客户端。而已。 Angular 应用程序可以根据需要定义任意数量的路由,但这些路由是客户端,Flask 服务器不参与其中。事实上,通过如此简单的设置,我不清楚为什么您需要在服务器上安装 Flask,看来您只是为您的 Angular 应用程序提供静态文件。
      • @Miguel 我没有混淆他们。考虑一下:我的角度应用程序在角度路线中带有“/”和“/about”。我也启用了 html5Mode。这意味着如果用户转到“/”,则会向服务器发送一个请求,然后启动 Angular 应用程序。当用户导航到“/about”时,请求不会转到服务器,因为 Angular 应用程序现在正在处理它。但是,如果用户刷新页面,“/about”将被发送到服务器。这意味着,服务器上需要有一个“/about”端点将请求传递到 angular。
      • 抱歉,是的,如果您希望用户从地址栏中显示的任何链接访问应用程序,那么您必须配置服务器以将所有这些 URL 重写为“/”所以始终提供主应用程序。刚刚在关于 html5 模式的 Angular 文档中找到了这一点:“使用这种模式需要在服务器端重写 URL,基本上你必须重写所有指向应用程序入口点的链接(例如 index.html)”
      • 我想指出,上面的答案是不正确的,并且错误地表明我的困惑根本不存在。很高兴在答案的开头反映这一点。
      猜你喜欢
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 2016-07-29
      • 2013-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      相关资源
      最近更新 更多