Add an Etag to client.js

This commit is contained in:
Frank A. Krueger 2017-12-09 17:02:04 -08:00
parent 877a835367
commit a96c3977f6
2 changed files with 50 additions and 12 deletions

View File

@ -30,12 +30,19 @@ namespace Microsoft.AspNetCore.Builder
if (context.Request.Path == jsPath) { if (context.Request.Path == jsPath) {
var response = context.Response; var response = context.Response;
var clientJsBytes = Ooui.UI.ClientJsBytes; var clientJsBytes = Ooui.UI.ClientJsBytes;
response.StatusCode = 200; var clientJsEtag = Ooui.UI.ClientJsEtag;
response.ContentLength = clientJsBytes.Length; if (context.Request.Headers.TryGetValue ("If-None-Match", out var inms) && inms.Count > 0 && inms[0] == clientJsEtag) {
response.ContentType = "application/javascript; charset=utf-8"; response.StatusCode = 304;
response.Headers.Add ("Cache-Control", "public, max-age=3600"); }
using (var s = response.Body) { else {
await s.WriteAsync (clientJsBytes, 0, clientJsBytes.Length).ConfigureAwait (false); response.StatusCode = 200;
response.ContentLength = clientJsBytes.Length;
response.ContentType = "application/javascript; charset=utf-8";
response.Headers.Add ("Cache-Control", "public, max-age=60");
response.Headers.Add ("Etag", clientJsEtag);
using (var s = response.Body) {
await s.WriteAsync (clientJsBytes, 0, clientJsBytes.Length).ConfigureAwait (false);
}
} }
} }
else if (context.Request.Path == WebSocketHandler.WebSocketPath) { else if (context.Request.Path == WebSocketHandler.WebSocketPath) {

View File

@ -14,6 +14,9 @@ namespace Ooui
{ {
static readonly ManualResetEvent started = new ManualResetEvent (false); static readonly ManualResetEvent started = new ManualResetEvent (false);
[ThreadStatic]
static System.Security.Cryptography.SHA256 sha256;
static CancellationTokenSource serverCts; static CancellationTokenSource serverCts;
static readonly Dictionary<string, RequestHandler> publishedPaths = static readonly Dictionary<string, RequestHandler> publishedPaths =
@ -26,8 +29,10 @@ namespace Ooui
public static StyleSelectors Styles => rules; public static StyleSelectors Styles => rules;
static readonly byte[] clientJsBytes; static readonly byte[] clientJsBytes;
static readonly string clientJsEtag;
public static byte[] ClientJsBytes => clientJsBytes; public static byte[] ClientJsBytes => clientJsBytes;
public static string ClientJsEtag => clientJsEtag;
public static string Template { get; set; } = $@"<!DOCTYPE html> public static string Template { get; set; } = $@"<!DOCTYPE html>
<html> <html>
@ -79,6 +84,22 @@ namespace Ooui
clientJsBytes = Encoding.UTF8.GetBytes (r.ReadToEnd ()); clientJsBytes = Encoding.UTF8.GetBytes (r.ReadToEnd ());
} }
} }
clientJsEtag = "\"" + Hash (clientJsBytes) + "\"";
}
static string Hash (byte[] bytes)
{
var sha = sha256;
if (sha == null) {
sha = System.Security.Cryptography.SHA256.Create ();
sha256 = sha;
}
var data = sha.ComputeHash (bytes);
StringBuilder sBuilder = new StringBuilder ();
for (int i = 0; i < data.Length; i++) {
sBuilder.Append (data[i].ToString ("x2"));
}
return sBuilder.ToString ();
} }
static void Publish (string path, RequestHandler handler) static void Publish (string path, RequestHandler handler)
@ -232,12 +253,22 @@ namespace Ooui
var response = listenerContext.Response; var response = listenerContext.Response;
if (path == "/ooui.js") { if (path == "/ooui.js") {
response.ContentLength64 = clientJsBytes.LongLength; var inm = listenerContext.Request.Headers.Get ("If-None-Match");
response.ContentType = "application/javascript"; if (string.IsNullOrEmpty (inm) || inm != clientJsEtag) {
response.ContentEncoding = Encoding.UTF8; response.StatusCode = 200;
response.AddHeader ("Cache-Control", "public, max-age=3600"); response.ContentLength64 = clientJsBytes.LongLength;
using (var s = response.OutputStream) { response.ContentType = "application/javascript";
s.Write (clientJsBytes, 0, clientJsBytes.Length); response.ContentEncoding = Encoding.UTF8;
response.AddHeader ("Cache-Control", "public, max-age=60");
response.AddHeader ("Etag", clientJsEtag);
using (var s = response.OutputStream) {
s.Write (clientJsBytes, 0, clientJsBytes.Length);
}
response.Close ();
}
else {
response.StatusCode = 304;
response.Close ();
} }
} }
else { else {