AngularJS routing hides 404 responses for nonexist

2019-06-03 01:50发布

I have noticed that GET requests for nonexistent paths don't return a 404 response. Instead, the client gets a "200 Ok", AngularJS renders the main view, and rewrites the path to /. A request for a nonsense URI is logged as successful in the server logs. If I understand correctly, the problem is that since AngularJS handles routing, the server has to accept a GET request for any URI and always respond by serving the client side of the app ("200 Ok" or "304 Not Modified").

For example, using the project scaffolded by the angular-fullstack Yeoman generator, requesting a nonexistent /unicorn goes like this:

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

The Express route that handles the request looks like this:

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

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

and index.jade is the root of the whole client side of the app.

After a quick look at the server side code of other AngularJS / Express projects on Github (AngularJS Express seed, AngularJS login), I see that this is a common pattern. I am wondering if there is a better way to handle requests for nonexistent paths, so that the client gets a real HTTP 404 response?

3条回答
爷的心禁止访问
2楼-- · 2019-06-03 02:20

You can use $route.otherwise() function In order to decide what to do with undefined Routes. If you want to still show a 404 message, You could simply set a /404.html route both in this Function and in express.

查看更多
Emotional °昔
3楼-- · 2019-06-03 02:22

The angular documentation has a section about the routing. Also, this question and this question have some information that pertains to IIS but could easily be adapted to express.

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)
查看更多
Ridiculous、
4楼-- · 2019-06-03 02:25

This is actually express handling routing--not angular. Remove the app.get('*', ... that you found to disable that.

查看更多
登录 后发表回答