Abstract request handlers

This is to support a larger variety of responses including
files for #8
This commit is contained in:
Frank A. Krueger 2017-07-06 16:01:21 -07:00
parent 1e16f91e76
commit 5a79d3646d
1 changed files with 56 additions and 22 deletions

View File

@ -14,8 +14,8 @@ namespace Ooui
{ {
static CancellationTokenSource serverCts; static CancellationTokenSource serverCts;
static readonly Dictionary<string, Func<Element>> publishedPaths = static readonly Dictionary<string, RequestHandler> publishedPaths =
new Dictionary<string, Func<Element>> (); new Dictionary<string, RequestHandler> ();
static readonly Dictionary<string, Style> styles = static readonly Dictionary<string, Style> styles =
new Dictionary<string, Style> (); new Dictionary<string, Style> ();
@ -78,7 +78,8 @@ namespace Ooui
public static void Publish (string path, Func<Element> elementCtor) public static void Publish (string path, Func<Element> elementCtor)
{ {
Console.WriteLine ($"PUBLISH {path}"); Console.WriteLine ($"PUBLISH {path}");
lock (publishedPaths) publishedPaths[path] = elementCtor; var handler = new ElementHandler (elementCtor);
lock (publishedPaths) publishedPaths[path] = handler;
Start (); Start ();
} }
@ -189,8 +190,6 @@ namespace Ooui
var response = listenerContext.Response; var response = listenerContext.Response;
Func<Element> ctor;
if (path == "/ooui.js") { if (path == "/ooui.js") {
response.ContentLength64 = clientJsBytes.LongLength; response.ContentLength64 = clientJsBytes.LongLength;
response.ContentType = "application/javascript"; response.ContentType = "application/javascript";
@ -202,9 +201,22 @@ namespace Ooui
} }
else { else {
var found = false; var found = false;
lock (publishedPaths) found = publishedPaths.TryGetValue (path, out ctor); RequestHandler handler;
lock (publishedPaths) found = publishedPaths.TryGetValue (path, out handler);
if (found) { if (found) {
WriteElementHtml (path, response); try {
handler.Respond (listenerContext, token);
}
catch (Exception ex) {
System.Console.WriteLine(ex);
try {
response.StatusCode = 500;
response.Close ();
}
catch {
// Ignore ending the response errors
}
}
} }
else { else {
response.StatusCode = 404; response.StatusCode = 404;
@ -213,22 +225,43 @@ namespace Ooui
} }
} }
static string RenderTemplate (string elementPath) abstract class RequestHandler
{ {
return Template.Replace ("@ElementPath", elementPath).Replace ("@Styles", rules.ToString ()); public abstract void Respond (HttpListenerContext listenerContext, CancellationToken token);
} }
static void WriteElementHtml (string elementPath, HttpListenerResponse response) class ElementHandler : RequestHandler
{ {
response.StatusCode = 200; readonly Lazy<Element> element;
response.ContentType = "text/html";
response.ContentEncoding = Encoding.UTF8; public ElementHandler (Func<Element> ctor)
var html = Encoding.UTF8.GetBytes (RenderTemplate (elementPath)); {
response.ContentLength64 = html.LongLength; element = new Lazy<Element> (ctor);
using (var s = response.OutputStream) { }
s.Write (html, 0, html.Length);
public Element GetElement () => element.Value;
public override void Respond (HttpListenerContext listenerContext, CancellationToken token)
{
var url = listenerContext.Request.Url;
var path = url.LocalPath;
var response = listenerContext.Response;
response.StatusCode = 200;
response.ContentType = "text/html";
response.ContentEncoding = Encoding.UTF8;
var html = Encoding.UTF8.GetBytes (RenderTemplate (path));
response.ContentLength64 = html.LongLength;
using (var s = response.OutputStream) {
s.Write (html, 0, html.Length);
}
response.Close ();
}
string RenderTemplate (string elementPath)
{
return Template.Replace ("@ElementPath", elementPath).Replace ("@Styles", rules.ToString ());
} }
response.Close ();
} }
static async void ProcessWebSocketRequest (HttpListenerContext listenerContext, CancellationToken serverToken) static async void ProcessWebSocketRequest (HttpListenerContext listenerContext, CancellationToken serverToken)
@ -239,10 +272,11 @@ namespace Ooui
var url = listenerContext.Request.Url; var url = listenerContext.Request.Url;
var path = url.LocalPath; var path = url.LocalPath;
Func<Element> ctor; RequestHandler handler;
var found = false; var found = false;
lock (publishedPaths) found = publishedPaths.TryGetValue (path, out ctor); lock (publishedPaths) found = publishedPaths.TryGetValue (path, out handler);
if (!found) { var elementHandler = handler as ElementHandler;
if (!found || elementHandler == null) {
listenerContext.Response.StatusCode = 404; listenerContext.Response.StatusCode = 404;
listenerContext.Response.Close (); listenerContext.Response.Close ();
return; return;
@ -250,7 +284,7 @@ namespace Ooui
Element element = null; Element element = null;
try { try {
element = ctor (); element = elementHandler.GetElement ();
} }
catch (Exception ex) { catch (Exception ex) {
listenerContext.Response.StatusCode = 500; listenerContext.Response.StatusCode = 500;