Received: by 10.224.206.135 with SMTP id fu7mr3180150qab.30.1314145614122; Tue, 23 Aug 2011 17:26:54 -0700 (PDT) X-BeenThere: liftweb@googlegroups.com Received: by 10.224.89.4 with SMTP id c4ls15928053qam.1.gmail; Tue, 23 Aug 2011 17:26:43 -0700 (PDT) MIME-Version: 1.0 Received: by 10.224.201.4 with SMTP id ey4mr403831qab.39.1314145603588; Tue, 23 Aug 2011 17:26:43 -0700 (PDT) Received: by er4g2000vbb.googlegroups.com with HTTP; Tue, 23 Aug 2011 17:26:43 -0700 (PDT) Date: Tue, 23 Aug 2011 17:26:43 -0700 (PDT) In-Reply-To: <2f690676-bdd9-4787-95dc-8e20a7b7a5d9@h7g2000yqm.googlegroups.com> References: <2f690676-bdd9-4787-95dc-8e20a7b7a5d9@h7g2000yqm.googlegroups.com> User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.215 Safari/535.1,gzip(gfe) Message-ID: Subject: Re: Enhanced stateless support in 2.4-master From: Alex Black To: Lift Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable I glossed over your point about cookies. So, if one wanted users to be stateless until some action took place you could: a. mark all requests as stateless by default b. if the user takes some action, then give them a cookie c. mark future requests as stateful if the cookie is present so I'm just thinking this through.. imagine: - request comes in, no cookie present, mark it as stateless - process the request, determine its a request to store some state and hence initiate a session - now, we cannot store that state in the session, because we're already stateless any thoughts? Perhaps I'm over complicating things, or perhaps there is a way around this. On Aug 23, 8:18=A0pm, Alex Black wrote: > Great, I'm looking forward to trying it out. > > Feedback: > - StatelessReqTest looks great, I can easily see how we can use that > to mark say requests from GoogleBot as stateless > - I haven't yet been able to understand the behavior trait, I'm not > following what use case its for, or how to use it, I'll read it over > again. > > I'm still interested in not creating sessions until they're needed, > but, thats probably just icing on the cake, being able to not give > sessions to crawlers should be a big help. > > - Alex > > On Aug 23, 5:05=A0pm, David Pollak > wrote: > > > > > > > > > Folks, > > > Based on some feedback from folks like Alex Black, I've enhanced Lift's > > support for stateless requests. > > > First, determining if a request should be stateless. =A0There's a new > > LiftRule: > > =A0 /** > > =A0 =A0* Certain paths and requests within your application can be mark= ed as > > stateless > > =A0 =A0* and if there is access to Lift's stateful facilities (setting > > =A0 =A0* SessionVars, updating function tables, etc.) the developer wil= l > > =A0 =A0* receive a notice and the operation will not complete. > > =A0 =A0*/ > > =A0 val statelessReqTest =3D RulesSeq[StatelessReqTestPF] > > > =A0 /** > > =A0 =A0* The test between the path of a request, the HTTP request, and = whether > > that path > > =A0 =A0* should result in stateless servicing of that path > > =A0 =A0*/ > > =A0 type StatelessReqTestPF =3D PartialFunction[StatelessReqTest, Boole= an] > > > /** > > =A0* The data structure that contains information to determine if the > > =A0* request should be treated as a stateful or stateless request > > =A0*/ > > final case class StatelessReqTest(path: List[String], httpReq: HTTPRequ= est) > > > You can now test the HTTPRequest for stuff like user agent, cookies, et= c. to > > determine if the request should be stateless. > > > Further, a Loc can be marked as stateless based on a function executed = at > > request time via LocParams: > > > =A0 /** > > =A0 =A0* A function that calculates the statelessness of the Loc for th= e given > > request > > =A0 =A0*/ > > =A0 case class CalcStateless(f: () =3D> Boolean) extends AnyLocParam > > > =A0 /** > > =A0 =A0* A function that calculates the statelessness of the Loc for th= e given > > request > > =A0 =A0* with the parameterized type passed into the function > > =A0 =A0*/ > > =A0 case class CalcParamStateless[-T](f: Box[T] =3D> Boolean) extends > > LocParam[T] > > > Finally, it's bad practice to ignore the state in stateless error boxes= . > > They mean that there's something wrong with your code. =A0However, it s= eems > > that some folks have snippets that access session state and just kinda > > ignore that sometimes these snippets execute in stateless mode because = in > > production mode the only bad thing that happens is that a log message i= s > > generated. > > > For those folks, I've added the following traits: > > > /** > > =A0* Mix this snippet into any snippet. =A0If the snippet is invoked in= response > > to a > > =A0* stateless request, then the behavior method is called with the met= hod > > name of > > =A0* the snippet (usually render, but there may be others if you specif= y a > > method > > =A0* after the snippet name: MySnippet.dothing). > > =A0*/ > > trait StatelessBehavior { > > =A0 /** > > =A0 =A0* Given the method name, return the transformation for the metho= d > > =A0 =A0*/ > > =A0 def behavior(methodName: String): NodeSeq =3D> NodeSeq > > > } > > > /** > > =A0* A simpler way to define behavior if the snippet is invoked. =A0Jus= t > > implement the behavior() method > > =A0* and all methods for the snippet will use that behavior. > > =A0*/ > > trait DefaultStatelessBehavior extends StatelessBehavior { > > =A0 def behavior(): NodeSeq =3D> NodeSeq > > =A0 def behavior(methodName: String): NodeSeq =3D> NodeSeq =3D behavior= () > > > } > > > /** > > =A0* A "default" implementation of StatelessBehavior. =A0Just ignore ev= erything > > and return a zero-length Text. > > =A0*/ > > trait BlankStatelessBehavior extends StatelessBehavior { > > =A0 def behavior(methodName: String): NodeSeq =3D> NodeSeq =3D ignore = =3D> Text("")} > > > Mix these traits into your the snippets that have stateful access. =A0T= he > > snippet execution will be short-circuited and the behavior defined in t= he > > StatelessBehavior will be used instead of the normal snippet behavior. = =A0Put > > simply, mix BlankStatelessBehavior into your snippets that display butt= ons > > and forms and such and instead of executing those snippets, you'll just= get > > empty Node in your output. > > > Questions? > > > Thanks, > > > David > > > PS -- Alex -- stateless is binary... a request is either handled in a > > stateless manner or not. =A0There's no tri-state or ability to toggle t= he > > statelessness based on user actions (although you could do so by puttin= g a > > marker cookie in responses of a certain type and then look for that coo= kie > > in the stateless test.) > > > -- > > Lift, the simply functional web frameworkhttp://liftweb.net > > Simply Lifthttp://simply.liftweb.net > > Follow me:http://twitter.com/dpp