【问题标题】:AngularJS routing hides 404 responses for nonexistent routesAngularJS 路由隐藏了不存在路由的 404 响应
【发布时间】:2014-01-10 00:02:58
【问题描述】:

我注意到对不存在路径的 GET 请求不会返回 404 响应。相反,客户端得到“200 Ok”,AngularJS 呈现主视图,并将路径重写为/。对无意义 URI 的请求在服务器日志中记录为成功。如果我理解正确,问题是由于 AngularJS 处理路由,服务器必须接受任何 URI 的 GET 请求,并始终通过为应用程序的客户端提供服务(“200 Ok”或“304 Not Modified”)来响应。

例如,使用由angular-fullstack Yeoman 生成器搭建的项目,请求一个不存在的/unicorn 如下:

GET /unicorn 200 31ms - 3.29kb
GET /partials/main 304 36ms
GET /api/awesomeThings 304 5ms

处理请求的 Express 路由如下所示:

// server, last route:
app.get('*', controllers.index);

// controllers:
exports.index = function(req, res) {
  res.render('index');
};

index.jade 是应用程序整个客户端的根。

在快速查看 Github 上其他 AngularJS / Express 项目的服务器端代码(AngularJS Express seedAngularJS login)后,我发现这是一种常见的模式。我想知道是否有更好的方法来处理对不存在路径的请求,以便客户端获得真正的 HTTP 404 响应?

【问题讨论】:

    标签: http angularjs express single-page-application


    【解决方案1】:

    角度documentation 有一个关于路由的部分。此外,这个question 和这个question 有一些与IIS 相关的信息,但可以很容易地适应表达。

    Html link rewriting
    When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as: <a href="/some?foo=bar">link</a>
    
    When a user clicks on this link,
    
    In a legacy browser, the URL changes to /index.html#!/some?foo=bar
    In a modern browser, the URL changes to /some?foo=bar
    In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.
    
    Links that contain target element
    Example: <a href="/ext/link?a=b" target="_self">link</a>
    Absolute links that go to a different domain
    Example: <a href="http://angularjs.org/">link</a>
    Links starting with '/' that lead to a different base path when base is defined
    Example: <a href="/not-my-base/link">link</a>
    When running Angular in the root of a domain, along side perhaps a normal application in the same directory, the "otherwise" route handler will try to handle all the URLs, including ones that map to static files.
    
    To prevent this, you can set your base href for the app to <base href="."> and then prefix links to URLs that should be handled with .. Now, links to locations, which are not to be routed by Angular, are not prefixed with . and will not be intercepted by the otherwise rule in your $routeProvider.
    
    Server side
    Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html)
    

    【讨论】:

      【解决方案2】:

      你可以使用 $route.otherwise() 函数 为了决定如何处理 undefined 路线。 如果您仍想显示 404 消息, 您可以在此 Function 和 express 中简单地设置 /404.html 路由。

      【讨论】:

      • 是的,我现在可能不得不接受这个,但仍然不会有来自服务器的实际 HTTP 404 响应。我有点担心这可能会产生什么样的问题。例如,如果我使用带有缓存的反向代理,并且某些机器人在路径的一部分中循环遍历随机 ID,那么缓存是否会被“200 OK”响应主体(404 页面)填满?这是一个人为的例子,但我的观点是偏离 HTTP 标准有点可怕。
      【解决方案3】:

      这实际上是express 处理路由——不是角度。删除您发现禁用它的app.get('*', ...

      【讨论】:

      • 但是,如果您在/ 以外的任何地方刷新页面,即使视图存在,您也会收到 404(或根本没有响应)。只有 Angular 知道哪些 URI 是有效的。
      • 您需要定义从您的服务器 URL 到 spa URL 的适当 URL 重写,这将是不同的。 Angular 不会在 spa 应用中生成 404。
      • @lucuma 所以,如果我理解正确的话,对于SPA使用的每个/partials/[view]路由,Express中都会有一个对应的顶级路由/[view],它将重定向到SPA url ,/#[view]。也许我应该使用路由表使其保持干燥。这听起来确实像我正在寻找的解决方案!如果您愿意回答,并附上相关文档或示例的链接,我将很乐意接受。
      • @DanRoss,我对表达的知识并不是很了解,但我会用角度文档中的适当信息添加答案。
      猜你喜欢
      • 2015-01-11
      • 1970-01-01
      • 2018-05-24
      • 1970-01-01
      • 2015-04-07
      • 2021-02-21
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      相关资源
      最近更新 更多