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”

  1. Alex Black Says:

    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

  2. Timothy Perrett Says:

    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

  3. Alex Black Says:

    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).

  4. Marius Says:

    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

  5. Alex Black Says:

    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!

  6. Timothy Perrett Says:

    Alex,

    Marius just committed a fix for your issue here: http://is.gd/9KznZ

    Cheers, Tim

Sorry, comments are closed for this article.