Fix returning to pages without re-requesting them

Chrome likes to cache HTML and was making a new web socket
request without first requesting a new page. The server however
expires a web socket url after its first use.

To fix this, web socket urls have a rolling cache policy and
can be reconnected to.

Fixes #52
This commit is contained in:
Frank A. Krueger 2018-02-01 15:09:37 -08:00
parent 0ff69fd3b7
commit f05f232d5b
3 changed files with 18 additions and 21 deletions

View File

@ -13,19 +13,19 @@ namespace Ooui.AspNetCore
public static TimeSpan SessionTimeout { get; set; } = TimeSpan.FromMinutes (5);
static readonly ConcurrentDictionary<string, PendingSession> pendingSessions =
new ConcurrentDictionary<string, PendingSession> ();
static readonly ConcurrentDictionary<string, ActiveSession> activeSessions =
new ConcurrentDictionary<string, ActiveSession> ();
public static string BeginSession (HttpContext context, Element element)
{
var id = Guid.NewGuid ().ToString ("N");
var s = new PendingSession {
var s = new ActiveSession {
Element = element,
RequestTimeUtc = DateTime.UtcNow,
LastConnectTimeUtc = DateTime.UtcNow,
};
if (!pendingSessions.TryAdd (id, s)) {
if (!activeSessions.TryAdd (id, s)) {
throw new Exception ("Failed to schedule pending session");
}
@ -60,20 +60,21 @@ namespace Ooui.AspNetCore
}
//
// Find the pending session
// Clear old sessions
//
if (!pendingSessions.TryRemove (id, out var pendingSession)) {
BadRequest ("Unknown `id`");
return;
var toClear = activeSessions.Where (x => (DateTime.UtcNow - x.Value.LastConnectTimeUtc) > SessionTimeout).ToList ();
foreach (var c in toClear) {
activeSessions.TryRemove (c.Key, out var _);
}
//
// Reject the session if it's old
// Find the pending session
//
if ((DateTime.UtcNow - pendingSession.RequestTimeUtc) > SessionTimeout) {
BadRequest ("Old `id`");
if (!activeSessions.TryGetValue (id, out var activeSession)) {
BadRequest ("Unknown `id`");
return;
}
activeSession.LastConnectTimeUtc = DateTime.UtcNow;
//
// Set the element's dimensions
@ -97,14 +98,14 @@ namespace Ooui.AspNetCore
//
var token = CancellationToken.None;
var webSocket = await context.WebSockets.AcceptWebSocketAsync ("ooui");
var session = new Ooui.UI.Session (webSocket, pendingSession.Element, w, h, token);
var session = new Ooui.UI.Session (webSocket, activeSession.Element, w, h, token);
await session.RunAsync ().ConfigureAwait (false);
}
class PendingSession
class ActiveSession
{
public Element Element;
public DateTime RequestTimeUtc;
public DateTime LastConnectTimeUtc;
}
}
}

View File

@ -37,7 +37,6 @@ function getSize () {
// Main entrypoint
function ooui (rootElementPath) {
var opened = false;
var initialSize = getSize ();
var wsArgs = (rootElementPath.indexOf("?") >= 0 ? "&" : "?") +
@ -47,11 +46,11 @@ function ooui (rootElementPath) {
if (location.protocol == "https:") {
proto = "wss";
}
socket = new WebSocket (proto + "://" + document.location.host + rootElementPath + wsArgs, "ooui");
socket.addEventListener ("open", function (event) {
console.log ("Web socket opened");
opened = true;
});
socket.addEventListener ("error", function (event) {
@ -60,10 +59,6 @@ function ooui (rootElementPath) {
socket.addEventListener ("close", function (event) {
console.error ("Web socket close", event);
if (opened) {
alert ("Connection to the server has been lost. Please try refreshing the page.");
opened = false;
}
});
socket.addEventListener("message", function (event) {

View File

@ -9,6 +9,7 @@
<div class="col-md-2">
<h1>Ooui</h1>
<p>Write interactive web apps in C# and F#</p>
<p><a href="https://github.com/praeclarum/Ooui">Source Code</a></p>
</div>
</div>