Created
May 10, 2011 19:17
-
-
Save Shadowfiend/965176 to your computer and use it in GitHub Desktop.
ReloadOnSessionLoss.setup can be run in Boot.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bootstrap.liftweb { | |
import net.liftweb.common._ | |
import net.liftweb.http._ | |
import js._ | |
import LiftRules._ | |
import net.liftweb.util.Helpers._ | |
/** | |
* Provides automatic reloading of the client on session loss. | |
* | |
* Lift keeps tweaking how they do this, but this is our tried-and-true | |
* approach for now. It's suggested that we keep monitoring Lift changes to | |
* how they do things so that we can adjust if they come up with a better | |
* strategy. One key difference is, at last check, Lift redirects the user to | |
* a set location (e.g., /) configured in LiftRules, whereas we reload the | |
* current page. | |
* | |
* Call ReloadOnSessionLoss.setup to install. | |
*/ | |
object ReloadOnSessionLoss { | |
def dispatch : DispatchPF = { | |
case req if firstSeenCometRequest_?(req) => () => Full(responseForFirstCometRequest(req)) | |
} | |
// Returns true if we should send an empty response for a comet request, | |
// false otherwise. This is used to ensure we don't send multiple | |
// window.location redirects in the event of a server restart in response | |
// to comet requests. Sending multiple ones can send Firefox into an | |
// infinite request loop that quickly consumes JVM resources and slows | |
// down the browser itself. | |
// | |
// It should only return true if this is the first time in this session | |
// that we see a comet request and meet the criteria for Lift sending | |
// back a window.location redirect to LiftRules.noCometSessionPage. Code | |
// for determining whether the actor list is empty was borrowed directly | |
// from LiftServlet.java. | |
def actorsForCometRequest(req:Req) : Box[List[(LiftCometActor, Long)]] = { | |
req.path.wholePath match { | |
case prefix :: tail if prefix == LiftRules.cometPath && (tail.length != 2 || tail(1) != LiftRules.cometScriptName()) => | |
Full( | |
req.params.toList.flatMap { | |
case (name, when) => | |
S.session.open_!.getAsyncComponent(name).toList.map(c => (c, toLong(when))) | |
} | |
) | |
case _ => Empty | |
} | |
} | |
def firstSeenCometRequest_?(req:Req) = { | |
(for { | |
actors <- actorsForCometRequest(req) | |
} yield { | |
actors.isEmpty | |
}) openOr ( | |
false | |
) | |
} | |
def responseForFirstCometRequest(req:Req) = { | |
JsCommands(List(new JE.JsRaw("lift_toWatch = {}; window.location.reload();") with JsCmd)).toResponse | |
} | |
def setup { | |
// It's important to do this in order to control our own session loss | |
// scenario. | |
LiftRules.redirectAjaxOnSessionLoss = false | |
LiftRules.dispatch.append(dispatch) | |
} | |
} | |
} |
In fact you're absolutely right, redirectLoc is a leftover from a slightly different approach to reloading that we had been using. Thanks for pointing that out!
I've updated the gist accordingly. Thanks again!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is line 61 redundant?
It looks like val redirectLoc is not used anywhere.