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

View File

@ -37,7 +37,6 @@ function getSize () {
// Main entrypoint // Main entrypoint
function ooui (rootElementPath) { function ooui (rootElementPath) {
var opened = false;
var initialSize = getSize (); var initialSize = getSize ();
var wsArgs = (rootElementPath.indexOf("?") >= 0 ? "&" : "?") + var wsArgs = (rootElementPath.indexOf("?") >= 0 ? "&" : "?") +
@ -47,11 +46,11 @@ function ooui (rootElementPath) {
if (location.protocol == "https:") { if (location.protocol == "https:") {
proto = "wss"; proto = "wss";
} }
socket = new WebSocket (proto + "://" + document.location.host + rootElementPath + wsArgs, "ooui"); socket = new WebSocket (proto + "://" + document.location.host + rootElementPath + wsArgs, "ooui");
socket.addEventListener ("open", function (event) { socket.addEventListener ("open", function (event) {
console.log ("Web socket opened"); console.log ("Web socket opened");
opened = true;
}); });
socket.addEventListener ("error", function (event) { socket.addEventListener ("error", function (event) {
@ -60,10 +59,6 @@ function ooui (rootElementPath) {
socket.addEventListener ("close", function (event) { socket.addEventListener ("close", function (event) {
console.error ("Web socket close", 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) { socket.addEventListener("message", function (event) {

View File

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