After upgrading to Lift 3.0-M3, some redirects are canceled if there's a comet actor on the page

54 views
Skip to first unread message

tenniscp25

unread,
Feb 18, 2015, 3:21:11 PM2/18/15
to lif...@googlegroups.com
Hello Lifters,

I found a different behavior of comets and redirects after upgrading Lift to 3.0-M3. My scenario is to log a user off if he stays inactive for 10 minutes and redirect him to the login page with a reason. I implemented this using JavaScript that upon timeout makes an ajax call to destroy his session and send him a redirect to a temporary page that does nothing but to setup a func on the login page and redirect him to it. This only works if no comet is on the page. I observe that the redirect to the login page with the mapped func is always canceled by `window.lift.settings.cometOnSessionLost`, which redirects the user to the root page.

Here's the code to demonstrate the behavior.

The SiteMap:
object AppSiteMap {
  val
TimeoutMessage = Menu.i("Timeout") / "timeoutMessage" >> EarlyResponse(() => Full(
   
RedirectWithState(
     
LoginPage.loc.calcDefaultHref,
     
RedirectState(() => S.error("timeout")))))

  val
LoginPage = Menu.i("Login") / "login"
}


index.html:
<lift:head>
<script data-lift="TimeoutScript" type="text/javascript"></script>
<script type="text/javascript">
  $
(document).ready(function() {
    setTimeout
(timeoutJsFunc, 10000);
 
});
</script>
</lift:head>


TimeoutScript.scala
object TimeoutScript {
 
def render = {
   
"*" #> Script(
     
JsCrVar("timeoutJsFunc",
       
AnonFunc(
         
SHtml.ajaxInvoke(() => {
            S
.session.foreach(_.destroySession())
           
RedirectTo(AppSiteMap.TimeoutMessage.loc.calcDefaultHref)
         
}))))
 
}
 
def uniqueId = "* *" #> S.session.map(_.uniqueId)
 
def underlyingId = "* *" #> S.session.map(_.underlyingId)
}


default.html:
<div data-lift="comet?type=AppComet&name=appComet"></div>


The no-op comet:
class AppComet extends MessageCometActor {
 
override def lowPriority = {
   
case "wontmatch" => ()
 
}  
}


The canceled request looks like this.


What's more interesting is that, this doesn't happen with all browsers. With Safari, it just always works like with Lift < 3.0-M3. With Firefox and IE, on the other hand, it always fails and redirects the user to the root page. For Chrome, it fails only if the page is on an active tab. Load the page with Chrome, quickly create and stay on the new tab without doing anything, it will do the redirect on the background tab correctly.


Thanks,

Pat

Antonio Salazar Cardozo

unread,
Feb 19, 2015, 9:56:37 AM2/19/15
to lif...@googlegroups.com
I'm surprised that worked to begin with, and would consider it an incorrect expectation that it work
the way it used to. Once the session is destroyed, all bets are off on whether you'll get a comet
expiration from an active comet.

Few things you can try:
 - Before calling the server-side timeout function that kills the session, turn off comet handling
   by calling lift.setToWatch({}).
 - Destroy the session on a page dedicated to destroying the session. Instead of AJAX calling
   to a function that destroys it, use window.location on the client to send them to a page that
   will do the same thing.
 - Replace lift.settings.cometOnSessionLost, or change LiftRules.noCometSessionCmd to not
   call it, so as to avoid that redirect. If you change cometOnSessionLost right before doing your
   server-side AJAX callback, you should be in good shape.

Thanks,
Antonio

tenniscp25

unread,
Feb 19, 2015, 11:44:16 AM2/19/15
to lif...@googlegroups.com
Thank you so much, Antonio. I added `lift.setToWatch({});` and now it just works!

Antonio Salazar Cardozo

unread,
Feb 19, 2015, 2:56:32 PM2/19/15
to lif...@googlegroups.com
Great to hear that it helped!
Thanks,
Antonio
Reply all
Reply to author
Forward
0 new messages