Permalink
Browse files

Merge pull request #1285 from lift/asc_issue_1285

Make session loss handling more flexible for ajax and comet
  • Loading branch information...
2 parents f6bdd84 + fd3edcf commit 03cab462a2d1d6db9ec829c9307019b48450c689 David Pollak committed Jul 1, 2012
@@ -598,11 +598,45 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable {
@volatile var liftCoreResourceName = "i18n.lift-core"
/**
- * Where to send the user if there's no comet session
+ * Where to send the user if there's no comet session. Note that this is
+ * contingent on an unchanged LiftRules.noCometSessionCommand and on
+ * liftComet.lift_sessionLost not being overridden client-side.
*/
+ @scala.deprecated("Use LiftRules.noCometSessionCmd.")
@volatile var noCometSessionPage = "/"
/**
+ * The JsCmd to execute when the comet session is lost. The comet
+ * session is considered lost when either (a) a comet request comes
+ * in for a session that does not exist on the server or (b) a comet
+ * request comes in for a session that has no associated comet actors
+ * (this typically happens when the server restarts).
+ *
+ * By default, we invoke liftComet.lift_sessionLost, which can be
+ * overridden client-side for more complex work.
+ * liftComet.lift_sessionLost redirects to
+ * LiftRules.noCometSessionPage by default for now, though
+ * noCometSessionPage is deprecated and will be replaced by a
+ * default of reloading the current page.
+ */
+ val noCometSessionCmd = new FactoryMaker[JsCmd](
+ () => JsCmds.Run("liftComet.lift_sessionLost()")
+ ) {}
+
+ /**
+ * The JsCmd to execute when the ajax session is lost. The ajax
+ * session is considered lost when either an ajax request comes in for
+ * a session that does not exist on the server.
+ *
+ * By default, we invoke liftAjax.lift_sessionLost, which can be
+ * overridden client-side for more complex work.
+ * liftAjax.lift_sessionLost reloads the page by default.
+ */
+ val noAjaxSessionCmd = new FactoryMaker[JsCmd](
+ () => JsCmds.Run("liftAjax.lift_sessionLost()")
+ ) {}
+
+ /**
* Put a function that will calculate the request timeout based on the
* incoming request.
*/
@@ -1315,11 +1349,16 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable {
private def logSnippetFailure(sf: SnippetFailure) = logger.info("Snippet Failure: " + sf)
/**
- * Set to false if you do not want Ajax/Comet requests that are not associated with a session
- * to cause a page reload
+ * Set to false if you do not want ajax/comet requests that are not
+ * associated with a session to call their respective session
+ * loss handlers (set via LiftRules.noAjaxSessionCmd and
+ * LiftRules.noCometSessionCmd).
*/
- @volatile var redirectAjaxOnSessionLoss = true
-
+ @volatile var redirectAsyncOnSessionLoss = true
+ @deprecated("Use redirectAsyncOnSessionLoss instead.")
+ def redirectAjaxOnSessionLoss = redirectAsyncOnSessionLoss
+ @deprecated("Use redirectAsyncOnSessionLoss instead.")
+ def redirectAjaxOnSessionLoss_=(updated:Boolean) = redirectAsyncOnSessionLoss = updated
/**
* The sequence of partial functions (pattern matching) for handling converting an exception to something to
@@ -214,22 +214,26 @@ class LiftServlet extends Loggable {
}.isDefined
}
- def isCometOrAjax(req: Req): Boolean = {
- val wp = req.path.wholePath
- val len = wp.length
-
- if (len < 2) false
+ val wp = req.path.wholePath
+ val pathLen = wp.length
+ def isComet: Boolean = {
+ if (pathLen < 2) false
else {
val kindaComet = wp.head == LiftRules.cometPath
- val cometScript = (len >= 3 && kindaComet &&
+ val cometScript = (pathLen >= 3 && kindaComet &&
wp(2) == LiftRules.cometScriptName())
+
+ (kindaComet && !cometScript) && req.acceptsJavaScript_?
+ }
+ }
+ def isAjax: Boolean = {
+ if (pathLen < 2) false
+ else {
val kindaAjax = wp.head == LiftRules.ajaxPath
- val ajaxScript = len >= 2 && kindaAjax &&
+ val ajaxScript = kindaAjax &&
wp(1) == LiftRules.ajaxScriptName()
-
- ((kindaComet && !cometScript) || (kindaAjax && !ajaxScript)) &&
- req.acceptsJavaScript_?
+ (kindaAjax && !ajaxScript) && req.acceptsJavaScript_?
}
}
@@ -241,20 +245,23 @@ class LiftServlet extends Loggable {
LiftRules.notFoundOrIgnore(req, Empty)
} else if (!authPassed_?(req)) {
Full(LiftRules.authentication.unauthorizedResponse)
- } else if (LiftRules.redirectAjaxOnSessionLoss && !hasSession(sessionIdCalc.id) && isCometOrAjax(req)) {
-
+ } else if (LiftRules.redirectAsyncOnSessionLoss && !hasSession(sessionIdCalc.id) && (isComet || isAjax)) {
val theId = sessionIdCalc.id
- // okay after 2 attempts to redirect, just
- // ignore calls to the comet URL
+
+ // okay after 2 attempts to redirect, just ignore calls to the
+ // async URL
if (recentlyChecked(theId) > 1) {
Empty
} else {
- Full(JavaScriptResponse(js.JE.JsRaw("window.location = " +
- (req.request.
- header("Referer") openOr
- "/").encJs).cmd, Nil, Nil, 200))
+ val cmd =
+ if (isComet)
+ js.JE.JsRaw(LiftRules.noCometSessionCmd.vend.toJsCmd + ";lift_toWatch = {};").cmd
+ else
+ js.JE.JsRaw(LiftRules.noAjaxSessionCmd.vend.toJsCmd).cmd
+
+ Full(new JsCommands(cmd :: Nil).toResponse)
}
- } else
+ }
// if the request is matched is defined in the stateless table, dispatch
if (S.statelessInit(req) {
tmpStatelessHolder = NamedPF.applyBox(req,
@@ -556,7 +563,7 @@ class LiftServlet extends Loggable {
sessionActor.getAsyncComponent(name).toList.map(c => (c, toLong(when)))
}
- if (actors.isEmpty) Left(Full(new JsCommands(new JE.JsRaw("lift_toWatch = {}") with JsCmd :: JsCmds.RedirectTo(LiftRules.noCometSessionPage) :: Nil).toResponse))
+ if (actors.isEmpty) Left(Full(new JsCommands(LiftRules.noCometSessionCmd.vend :: js.JE.JsRaw("lift_toWatch = {};").cmd :: Nil).toResponse))
else requestState.request.suspendResumeSupport_? match {
case true => {
setupContinuation(requestState, sessionActor, actors)
@@ -111,6 +111,11 @@ object ScriptRenderer {
"""
},
+
+ lift_sessionLost: function() {
+ location.reload();
+ },
+
lift_doAjaxCycle: function() {
if (liftAjax.lift_doCycleQueueCnt > 0) liftAjax.lift_doCycleQueueCnt--;
var queue = liftAjax.lift_ajaxQueue;
@@ -251,6 +256,10 @@ object ScriptRenderer {
setTimeout("liftComet.lift_cometEntry();",""" + LiftRules.cometFailureRetryTimeout + """);
},
+ lift_sessionLost: function() { """ +
+ JsCmds.RedirectTo(LiftRules.noCometSessionPage).toJsCmd +
+ """},
+
lift_cometEntry: function() {
var isEmpty = function(){for (var i in lift_toWatch) {return false} return true}();
if (!isEmpty) {

0 comments on commit 03cab46

Please sign in to comment.