Gracefully handling 404s with Lift
February 21st, 2010
In my continuing effort to improve the wider knowledge of Lift, here’s another great nugget that shows you how to provide a 404 handler powered from a Lift template
class Boot {
def boot {
// ...other stuff...
LiftRules.uriNotFound.prepend(NamedPF("404handler"){
case (req,failure) =>
NotFoundAsTemplate(ParsePath(List("404"),"html",false,false))
})
}
}
And I have a 404.html file in the ./webapp/404.html with the contents:
<lift:surround with="default" at="content">
<h2>Ooops!</h2>
<p>Wow, we totally couldn't find your page. Sorry about that.</p>
</lift:surround>
Then whenever a user browses to a URL that is not supported by your application, you can give them a friendly (and nicely designed) webpage rather than some technical message about 404s.
Note: The only cavet is not to use the <lift:menu /> snippet within your 404 template because Lift is unable to calculate the SiteMap when its a URL that is not accounted for within that scheme.
UPDATE The above note is now redundant because of commit by Marius on issue 376
6 Responses to “Gracefully handling 404s with Lift”
Sorry, comments are closed for this article.
February 21st, 2010 at 05:40 PM
Hi Tim,
I posted something similar a while back after discussing this on the lift group (probably with you I imagine!).
See: http://code.alexblack.ca/creating-a-custom-404-error-page-using-lift
I wasn’t happy with a 404 page with no sitemap (e.g. it’d be nice to show the user a menu so they can navigate somewhere else), and also wanted head-merge capability. My article (above) shows how to do both, but its a bit of a hack.
I look forward to future versions of Lift that might make this easer!
- Alex
February 21st, 2010 at 09:06 PM
Alex, yes, I know you posted and I remember the discussion on the list. The solution I detail here is the “fixed” solution as opposed to the one you posted (that is, we made changes to lift after the discussion)
For several reasons, im not sure that we will alter sitemap to handle these 404s because that would fundamentally break the expected sitemap in a few ways as the whole premise of sitemap is that it can only work with pages that it knows about and are under its control. As you have already found, catch-all Loc’s open a security hole, so I think the current solution is a fair compromise.
Thanks for the interest.
Tim
February 22nd, 2010 at 05:23 PM
Hi Tim, great to see the new code.
As far as the sitemap goes, clearly it makes sense to show a sitemap on all pages so users can navigate, so I think the question is how can lift accomodate this need?
I don’t know much about how stuff works, but the first thing that comes to mind is to tell the sitemap about the location of the 404 page.
In fact, its seems to make sense that if you ask the site for a page that doesn’t exist, the sitemap should know this, and should then show you a 404 page (implying it nows about the 404 page).
February 22nd, 2010 at 09:48 PM
Alex,
Lift’s SiteMap relies on the Req information. In order to have the SiteMap menu snippet we’d have to hack the Req and feed in a fake Req with the 404’s URI instead the client’s URI. Thus the user would see a 404 page with a menu show with a URI that is pointing to nowhere.
Faking the Req shouldn’t be awfully hard but quite tricky.
I’m not 100% convinced we should do this but I can at least looking in ways of doing it. I understand the end user perspective and Tim is also right that this can also be seen as a disruption of the SiteMap as the SiteMap is point Locations corresponding to the clients request.
Br’,s Marius
February 25th, 2010 at 02:32 AM
Hi Marius,
I can imagine there are some challenges, and I don’t mean to suggest any particular implementation, you guys definitely know much more than I about Lift.
But, being less familiar with its inner workings I do have one advantage: I’m not as close to it.
Hopefully there is a solution that will work well here, so that future users can have nice 404 pages with links to the rest of the site!
March 5th, 2010 at 02:05 PM
Alex,
Marius just committed a fix for your issue here: http://is.gd/9KznZ
Cheers, Tim