Please see my previous reply and the proposed solution. Br's, Marius
On Dec 30, 6:12 pm, Ross Mellgren <dri...@gmail.com> wrote: > Ouch, it does sound ugly. Is there some alternative way to change the > currently requested URI, for the purposes of sitemap generation and so > on? It seems like the alternative is spinning one's own SiteMap menu > snippet that knows to do this work? > > Also, it seems odd there's no way to invoke the normal template flow > even barring the re-init of S. The closest you can get that I know of > is LiftSession.processSurroundAndInclude or S.render, but neither of > those do head merge which seems to be a very key part of the rendering > pipeline. Perhaps I'm misreading the code? It looks like > LiftMerge.merge is called from LiftSession.processRequest which is > called from LiftServlet.dispatchStatefulRequest, and so on, all > private to net.liftweb.http. > > At any rate, I'm just trying to help Alex, I'm not invested in any > reason other than it's informative to try and solve. Is there any way > to get a templated 404 response? > > -Ross > > On Dec 30, 2009, at 4:32 AM, Marius wrote: > > > Re init-ing S is a very risky thing to do. You loose all your context > > information. uriNotFound is called by Lift from several key points. > > From those key points, Lift uses the S context and updates the > > function Map. With your example if your template is binding Scala > > functions, those function will be written to a function map that will > > not be seen by Lift as you're writing to a different S context. > > > I would advice no doing such things or if you do, then expect side > > effects. In general avoid bypassing Lift's rendering pipeline. Lift > > does a lot of things some of them internal and missing those you can > > get into nasty hidden problems. > > > For head merge you could use HeadHelper.scala but note that internally > > Lift doesn't use this ... it uses a more sophisticated head merge ... > > see LiftMerge.scala. HeadHelper holds the old merge. IMO it should be > > removed. > > > I'm not really sure why you guys don't like redirects, probably to > > avoid traffic, but IMO this is not very relevant. But regardless, you > > guys have your own reasons. > > > Br's, > > Marius > > > On Dec 30, 9:39 am, Ross Mellgren <dri...@gmail.com> wrote: > >> I think the problem with the site map is that the request you have > >> is for a page that doesn't exist so it can't build the current-page- > >> relative sitemap. > > >> Here's a version that works: > > >> In Boot: > > >> val notFoundNode = <lift:embed what="404" /> > >> LiftRules.uriNotFound.prepend { > >> case _ => XhtmlTemplateResponse(notFoundNode, 404) > >> } > > >> And the other part: > > >> object XhtmlTemplateResponse extends HeaderStuff { > >> def apply(nodeToRender: NodeSeq, statusCode: Int): LiftResponse > >> = { > >> val renderedNode = { > >> val forceToRoot: LiftRules.RewritePF = { case _ => > >> RewriteResponse(Req.parsePath("/"), TreeMap.empty, true) } > >> for (req <- S.request; session <- S.session) yield > >> S.init(Req(req, forceToRoot::Nil), session) { > >> session.processSurroundAndInclude("/", > >> nodeToRender) > >> } > >> } openOr { > >> error("No session") > >> } > > >> new XhtmlResponse(Group(renderedNode), Empty, headers, > >> cookies, statusCode, false) > >> } > > >> } > > >> The secret sauce is reiniting S with a new request that has been > >> rewritten to seem as if it were a hit to / > > >> I'm not sure if this is a good idea, but it seems to work for the > >> site map thing. > > >> However, I can't find a way to make the head merge work properly. > >> It looks like the head merging lies in the code path inside > >> LiftSession that is private to Lift. You could rearrange your > >> template to make only one head I guess, or wait until someone more > >> wise than I can direct you as far as that goes. > > >> -Ross > > >> On Dec 30, 2009, at 12:32 AM, Alex Black wrote: > > >>> I noticed another problem: the head merge is not working in this > >>> scenario, the resulting page is not valid XHTML because it has two > >>> head tags :) So, this makes me think I'm going about things the > >>> wrong > >>> way. > > >>> I'm hoping you can suggest the right way, to create a custom 404 > >>> page, > >>> correctly (without a redirect, with 404 status code), and > >>> processed by > >>> the template engine so it uses our default template with sitemap > >>> etc. > > >>> - Alex > > >>> On Dec 30, 12:22 am, Alex Black <a...@alexblack.ca> wrote: > >>>> One more detail: > > >>>> notFoundNode is defined like this: > > >>>> val notFoundNode = <lift:embed what="404" /> > > >>>> and 404.html like this: > > >>>> <lift:surround with="default" at="content"> > >>>> <head> > >>>> <title>Page Not Found</title> > >>>> </head> > >>>> <h1>Page Not Found</h1> > >>>> <p>We couldn't find the page you were looking for.</p> > >>>> </lift:surround> > > >>>> And my default.html hidden template has a site map tag in it, and > >>>> the > >>>> sitemap contains a number of entries. > > >>>> On Dec 30, 12:14 am, Alex Black <a...@alexblack.ca> wrote: > > >>>>> I emailed Ross directly and said I did run with - > >>>>> Drun.mode=production. > > >>>>> Here's what I'm seeing: > >>>>> 1. If I run with -Drun.mode=production, and I access a not found > >>>>> url, > >>>>> say mysite.com/foobar, then, I *do* see the custom 404 page as > >>>>> expected, but, where I normally see my sitemap I see "No > >>>>> Navigation > >>>>> Defined". > >>>>> 2. If I run *without* that production flag, and I access a not > >>>>> found > >>>>> url, I get a blank white screen that says "The requested page > >>>>> was not > >>>>> defined in your SiteMap, so access was blocked. (This message is > >>>>> displayed in development mode only)". > > >>>>> So #2 is expected, #1 is not. > > >>>>> Ross, when you emailed me you said you tried to reproduce this, > >>>>> but I > >>>>> think one difference between your scenario and mine is that on > >>>>> my 404 > >>>>> page I have a sitemap rendered. > > >>>>> So instead of what dpp had: > > >>>>> LiftRules.uriNotFound.prepend { > >>>>> case _ => XhtmlResponse((<html> <body>Silly goose</body> </ > >>>>> html>), > >>>>> Empty, List("Content-Type" -> > >>>>> "text/ > >>>>> html; > >>>>> charset=utf-8"), Nil, 404, S.ieMode) > >>>>> } > > >>>>> I have: > > >>>>> // Catch 404s > >>>>> LiftRules.uriNotFound.prepend { > >>>>> case (req, _) => XhtmlTemplateResponse(notFoundNode, 404) > >>>>> } > > >>>>> with > > >>>>> object XhtmlTemplateResponse extends HeaderStuff { > >>>>> def apply(nodeToRender: Node, statusCode: Int): LiftResponse = { > >>>>> val renderedNode = S.render(nodeToRender, > >>>>> S.request.get.request).first > >>>>> new XhtmlResponse(renderedNode, Empty, headers, cookies, > >>>>> statusCode, false) > >>>>> } > > >>>>> } > > >>>>> - Alex > > >>>>> On Dec 29, 7:49 pm, Ross Mellgren <dri...@gmail.com> wrote: > > >>>>>> This is the production run mode thing dpp talked about. Try > >>>>>> your app with -Drun.mode=production > > >>>>>> -Ross > > >>>>>> On Dec 29, 2009, at 7:39 PM, Alex Black wrote: > > >>>>>>> Thanks for pointing that out, the catch-all sounds dangerous. > > >>>>>>> I tried your suggestion, and it works well except I'm > >>>>>>> encountering one > >>>>>>> issue, my sitemap renders as "No Navigation Defined." for urls > >>>>>>> that > >>>>>>> are not found. I'm using 1.1-M8, I launched jetty in > >>>>>>> production mode > >>>>>>> as you indicated, and added the passNotFoundToChain = false. > > >>>>>>> Did you expect that - or is the passNotFoundToChain meant to > >>>>>>> solve the > >>>>>>> sitemap issue? > > >>>>>>> - Alex > > >>>>>>> On Dec 29, 6:10 pm, David Pollak <feeder.of.the.be...@gmail.com> > >>>>>>> wrote: > >>>>>>>> Keep in mind that Lift's behavior for 404s differs between > >>>>>>>> development and > >>>>>>>> production mode in Lift 1.1-xxx > > >>>>>>>> To have your app/Lift handle a 404 rather than passing it to > >>>>>>>> your web > >>>>>>>> container, in Boot.scala: > > >>>>>>>> LiftRules.passNotFoundToChain = false > > >>>>>>>> LiftRules.uriNotFound.prepend { > >>>>>>>> case _ => XhtmlResponse((<html> <body>Silly goose</ > >>>>>>>> body> </html>), > >>>>>>>> Empty, List("Content-Type" -> > >>>>>>>> "text/html; > >>>>>>>> charset=utf-8"), Nil, 404, S.ieMode) > >>>>>>>> } > > >>>>>>>> In development mode, Lift will tell you about SiteMap as this > >>>>>>>> was a common > >>>>>>>> confusion point among new developers. In production mode, > >>>>>>>> Lift will use > >>>>>>>> that code. To put Lift in production mode: > > >>>>>>>> mvn -Drun.mode=production jetty:run > > >>>>>>>> I would strongly recommend against a "catch-all" entry in > >>>>>>>> SiteMap as it will > >>>>>>>> expose every page on your site to access. > > >>>>>>>> On Tue, Dec 29, 2009 at 11:17 AM, Alex Black > >>>>>>>> <a...@alexblack.ca> wrote: > >>>>>>>>> Ok, I got this working, with 1.1-M8 using S.render. > > >>>>>>>>> // A node which embeds our 404 template (e.g. 404.html) > >>>>>>>>> val notFoundNode = > >>>>>>>>> <lift:embed what="404" /> > > >>>>>>>>> // Catch 404s > >>>>>>>>> LiftRules.uriNotFound.prepend { > >>>>>>>>> case (req, _) => XhtmlTemplateResponse(notFoundNode, 404) > >>>>>>>>> } > > >>>>>>>>> // If you're using a sitemap, make sure you have a catch- > >>>>>>>>> all item, > >>>>>>>>> e.g > >>>>>>>>> // Menu(Loc("Catchall", Pair(Nil, true), "", Hidden :: > >>>>>>>>> Nil)) :: > > >>>>>>>>> using this object: > > >>>>>>>>> object XhtmlTemplateResponse extends HeaderStuff { > >>>>>>>>> def apply(nodeToRender: Node, statusCode: Int): > >>>>>>>>> LiftResponse = { > >>>>>>>>> val renderedNode = S.render(nodeToRender, > >>>>>>>>> S.request.get.request).first > >>>>>>>>> new XhtmlResponse(renderedNode, Empty, headers, cookies, > >>>>>>>>> statusCode, false) > >>>>>>>>> } > >>>>>>>>> } > > >>>>>>>>> I think the wiki page: > >>>>>>>>>http://wiki.liftweb.net/index.php/Setting_up_a_custom_404_page > >>>>>>>>> should be updated. The current code hides the 404 status > > ... > > read more » -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.