Open ivan-kleshnin opened 9 years ago
First and foremost, you should do that on the server so that you get a proper 404 HTTP response. On the client though... I'm guessing you're either successfully matching a route pattern, in which case you can check the validity of the route arguments when they are matched, or you're not matching any route pattern, in which case the click handler won't match the url to a path and will let the request go through to the server, which will result in a 404.
I think something is wrong in this assumptions.
Server is API + answer-with-frontend-app-to-any-route universal endpoint.
// no info to answer 404 withing the routes corresponding to Frontend application
router.get("*", function (req, res, cb) { app
if (req.path.startsWith("/public/")) {
return cb();
} else if (req.path.startsWith("/api/")) {
return cb();
} else {
...
return res.render(...);
}
So in the frontend-first architectures server has no knowledge about unexistance of routes unless frontend grants him with that information (isomorphic apps).
So this
in which case the click handler won't match the url to a path and will let the request go through to the server, which will result in a 404.
is either impossible to implement or this thing can (and should) be at the frontend first.
We have to catch "click handler found no match" events and handle them by displaying "Page Not Found".
This is not a strict equivalent of Server 404.
In old-school backend-first architectures there could be two types of "404 Page Not Found".
First: no route matched. Second: route matched, params parsed but id (or other thing) does not correspond to any database model.
Only first situation is applicable to frontend-first architectures. Second case translates to server responds with 404 inner event and we commonly represent this as notification. Not as "Page Not Found".
Sorry my bad, you are right. So I guess I don't really understand what you want then. I mean, presumably you've got a route listener in there somewhere, and upon receiving a message that the route has transitioned, you're looking at the route parameters and using that to judge what content to load, right?
e.g. if your route is /pets/:id
and you get a state transition for /pets/fluffy
, and upon checking your database it turns out that you have no pet named fluffy, then you would send a navigation request to the router.
Is the "navigate" method what you're looking for? (i.e. targeting an error route, such as /error/404
)
For what it's worth, I'm nearly finished completely rewriting the router, and there will be a number of significant breaking changes. The changes to your code shouldn't be significant though.
So I guess I don't really understand what you want then.
As I said, there is two common possible situations. Let's call them page-not-found and data-not-found. The case you've described is data-not-found. And this case is already working. I can react to 404 HTTP server response in a number of ways. This is not strictly connected with cycle-router5, maybe worth only documenting.
So page-not-found is left.
What I want is to get some event when I access unexisting route on frontend.
The case when backend responds with existing frontend app bundle and frontend app have to warn users that they try to access unexisting page, for example misspelling like /abouT
.
And let's suppose this is not isomorphic app, for example it has Python or Java on backend. We can't ignore this case, right?!
Saying that, I'm experementing with Router5 and have discovered a number of issues. For example, I can't hook to anything to possibly get into "Page Not Found" state.
https://github.com/router5/router5/issues/22
.start()
behavior is also very strange.
For what it's worth, I'm nearly finished completely rewriting the router, and there will be a number of significant breaking changes. The changes to your code shouldn't be significant though.
That's great.
https://github.com/router5/router5/issues/22 is fixed and now we have two (at least) approaches to implement page-not-found. Note: the code below corresponds to pure Router-5, not Cycle-Router5.
page-not-found
the default routelet router = new Router5(undefined, {
defaultRoute: "page-not-found",
});
router
.addNode("page-not-found", "/page-not-found")
.start()
Access to /dfdsfsfdsf
triggers redirect to /page-not-found
, which may invoke appropriate listeners.
onTransitionError
let router = new Router5(undefined, {
defaultRoute: undefined,
});
router
.onTransitionError(handleErrors);
.start();
Access to /dfdsfsfdsf
triggers handleErrors
, which may invoke appropriate listeners.
First option seems easier to implement (just add not-found page) but it does not behave in-line with backend which will cripple our isomorphic intentions. So I'd go with second one or find another approach.
How to implement?