Add UI.PublishFile for static files

Fixes #8
This commit is contained in:
Frank A. Krueger 2017-07-07 19:38:04 -07:00
parent 9f34f5f428
commit cd8c96a27c
3 changed files with 126 additions and 9 deletions

View File

@ -12,6 +12,8 @@ namespace Ooui
{ {
public static class UI public static class UI
{ {
static readonly ManualResetEvent started = new ManualResetEvent (false);
static CancellationTokenSource serverCts; static CancellationTokenSource serverCts;
static readonly Dictionary<string, RequestHandler> publishedPaths = static readonly Dictionary<string, RequestHandler> publishedPaths =
@ -77,27 +79,60 @@ namespace Ooui
} }
} }
public static void Publish (string path, Func<Element> elementCtor) static void Publish (string path, RequestHandler handler)
{ {
Console.WriteLine ($"PUBLISH {path}"); Console.WriteLine ($"PUBLISH {path} {handler}");
var handler = new ElementHandler (elementCtor);
lock (publishedPaths) publishedPaths[path] = handler; lock (publishedPaths) publishedPaths[path] = handler;
Start (); Start ();
} }
public static void Publish (string path, Func<Element> elementCtor)
{
Publish (path, new ElementHandler (elementCtor));
}
public static void Publish (string path, Element element) public static void Publish (string path, Element element)
{ {
Publish (path, () => element); Publish (path, () => element);
} }
public static void PublishFile (string filePath)
{
var path = "/" + System.IO.Path.GetFileName (filePath);
PublishFile (path, filePath);
}
public static void PublishFile (string path, string filePath, string contentType = null, string contentEncoding = null)
{
var data = System.IO.File.ReadAllBytes (filePath);
if (contentType == null) {
contentType = GuessContentType (path, filePath);
}
Publish (path, new DataHandler (data, contentType, contentEncoding));
}
static string GuessContentType (string path, string filePath)
{
return null;
}
public static void Present (string path, object presenter = null) public static void Present (string path, object presenter = null)
{ {
var localHost = host == "*" ? "localhost" : host; WaitUntilStarted ();
var url = $"http://{localHost}:{port}{path}"; var url = GetUrl (path);
Console.WriteLine ($"PRESENT {url}"); Console.WriteLine ($"PRESENT {url}");
Platform.OpenBrowser (url, presenter); Platform.OpenBrowser (url, presenter);
} }
public static string GetUrl (string path)
{
var localhost = host == "*" ? "localhost" : host;
var url = $"http://{localhost}:{port}{path}";
return url;
}
public static void WaitUntilStarted () => started.WaitOne ();
static void Start () static void Start ()
{ {
if (serverCts != null) return; if (serverCts != null) return;
@ -112,6 +147,7 @@ namespace Ooui
var scts = serverCts; var scts = serverCts;
if (scts == null) return; if (scts == null) return;
serverCts = null; serverCts = null;
started.Reset ();
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine ($"Stopping..."); Console.WriteLine ($"Stopping...");
@ -131,13 +167,13 @@ namespace Ooui
{ {
HttpListener listener = null; HttpListener listener = null;
var started = false; started.Reset ();
while (!started && !token.IsCancellationRequested) { while (!started.WaitOne(0) && !token.IsCancellationRequested) {
try { try {
listener = new HttpListener (); listener = new HttpListener ();
listener.Prefixes.Add (listenerPrefix); listener.Prefixes.Add (listenerPrefix);
listener.Start (); listener.Start ();
started = true; started.Set ();
} }
catch (System.Net.Sockets.SocketException ex) when catch (System.Net.Sockets.SocketException ex) when
(ex.SocketErrorCode == System.Net.Sockets.SocketError.AddressAlreadyInUse) { (ex.SocketErrorCode == System.Net.Sockets.SocketError.AddressAlreadyInUse) {
@ -244,6 +280,39 @@ namespace Ooui
} }
} }
class DataHandler : RequestHandler
{
readonly byte[] data;
readonly string contentType;
readonly string contentEncoding;
public DataHandler (byte[] data, string contentType = null, string contentEncoding = null)
{
this.data = data;
this.contentType = contentType;
this.contentEncoding = contentEncoding;
}
public override void Respond (HttpListenerContext listenerContext, CancellationToken token)
{
var url = listenerContext.Request.Url;
var path = url.LocalPath;
var response = listenerContext.Response;
response.StatusCode = 200;
if (!string.IsNullOrEmpty (contentType))
response.ContentType = contentType;
if (!string.IsNullOrEmpty (contentEncoding))
response.ContentType = contentEncoding;
response.ContentLength64 = data.LongLength;
using (var s = response.OutputStream) {
s.Write (data, 0, data.Length);
}
response.Close ();
}
}
static async void ProcessWebSocketRequest (HttpListenerContext listenerContext, CancellationToken serverToken) static async void ProcessWebSocketRequest (HttpListenerContext listenerContext, CancellationToken serverToken)
{ {
// //

View File

@ -5,7 +5,7 @@ using NUnit.Framework;
using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
using TestMethodAttribute = NUnit.Framework.TestCaseAttribute; using TestMethodAttribute = NUnit.Framework.TestCaseAttribute;
#else #else
using MicrosofVisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif #endif
using Ooui; using Ooui;

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Net.Http;
using System.Threading.Tasks;
#if NUNIT #if NUNIT
using NUnit.Framework; using NUnit.Framework;
@ -60,5 +62,51 @@ namespace Tests
Assert.AreEqual ("inherit", UI.Styles[".t3"].BackgroundColor); Assert.AreEqual ("inherit", UI.Styles[".t3"].BackgroundColor);
Assert.AreEqual ("", UI.Styles.ToString ()); Assert.AreEqual ("", UI.Styles.ToString ());
} }
[TestMethod]
public void PublishMissingFileFails ()
{
try {
UI.PublishFile ("/file", "a file that doesn't exist");
Assert.Fail ("Publishing not existing file should fail");
}
catch (System.IO.FileNotFoundException) {
}
}
[TestMethod]
public void PublishEmptyFile ()
{
var f = System.IO.Path.GetTempFileName ();
UI.PublishFile ("/file", f);
UI.WaitUntilStarted ();
var c = new System.Net.WebClient ();
var r = c.DownloadString (UI.GetUrl ("/file"));
Assert.AreEqual ("", r);
}
[TestMethod]
public void PublishTextFile ()
{
var f = System.IO.Path.GetTempFileName ();
System.IO.File.WriteAllText (f, "Test Ooui Text File", System.Text.Encoding.UTF8);
UI.PublishFile ("/text-file", f, "text/plain", "utf-8");
UI.WaitUntilStarted ();
var c = new System.Net.WebClient ();
var r = c.DownloadString (UI.GetUrl ("/text-file"));
Assert.AreEqual ("Test Ooui Text File", r);
}
[TestMethod]
public void PublishFileWithoutPath ()
{
var f = System.IO.Path.GetTempFileName ();
System.IO.File.WriteAllText (f, "Test Ooui Text File 2", System.Text.Encoding.UTF8);
UI.PublishFile (f);
UI.WaitUntilStarted ();
var c = new System.Net.WebClient ();
var r = c.DownloadString (UI.GetUrl ("/" + System.IO.Path.GetFileName (f)));
Assert.AreEqual ("Test Ooui Text File 2", r);
}
} }
} }