Files
velopack/test/TestHelpers/StaticHttpServer.cs
T

97 lines
2.9 KiB
C#
Raw Normal View History

2014-07-28 10:53:28 +02:00
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
2014-07-28 11:12:14 +02:00
using System.Threading.Tasks;
2014-07-28 10:53:28 +02:00
namespace Squirrel.Tests
{
public sealed class StaticHttpServer : IDisposable
{
public int Port { get; private set; }
public string RootPath { get; private set; }
IDisposable inner;
public StaticHttpServer(int port, string rootPath)
{
Port = port; RootPath = rootPath;
}
public IDisposable Start()
{
if (inner != null) {
throw new InvalidOperationException("Already started!");
}
var server = new HttpListener();
server.Prefixes.Add(String.Format("http://+:{0}/", Port));
server.Start();
2014-07-28 11:12:14 +02:00
bool shouldStop = false;
var listener = Task.Run(async () => {
while (!shouldStop) {
var ctx = await server.GetContextAsync();
2014-07-28 10:53:28 +02:00
if (ctx.Request.HttpMethod != "GET") {
closeResponseWith(ctx, 400, "GETs only");
return;
}
var target = Path.Combine(RootPath, ctx.Request.Url.AbsolutePath.Replace('/', Path.DirectorySeparatorChar).Substring(1));
var fi = new FileInfo(target);
if (!fi.FullName.StartsWith(RootPath)) {
closeResponseWith(ctx, 401, "Not authorized");
return;
}
if (!fi.Exists) {
closeResponseWith(ctx, 404, "Not found");
return;
}
try {
using (var input = File.OpenRead(target)) {
ctx.Response.StatusCode = 200;
input.CopyTo(ctx.Response.OutputStream);
ctx.Response.Close();
}
} catch (Exception ex) {
closeResponseWith(ctx, 500, ex.ToString());
}
2014-07-28 11:12:14 +02:00
}
});
2014-07-28 10:53:28 +02:00
var ret = Disposable.Create(() => {
2014-07-28 11:12:14 +02:00
shouldStop = true;
2014-07-28 10:53:28 +02:00
server.Stop();
2014-07-28 11:12:14 +02:00
listener.Wait(2000);
2014-07-28 10:53:28 +02:00
inner = null;
});
inner = ret;
return ret;
}
static void closeResponseWith(HttpListenerContext ctx, int statusCode, string message)
{
ctx.Response.StatusCode = statusCode;
using (var sw = new StreamWriter(ctx.Response.OutputStream, Encoding.UTF8)) {
sw.WriteLine(message);
}
ctx.Response.Close();
}
public void Dispose()
{
var toDispose = Interlocked.Exchange(ref inner, null);
if (toDispose != null) {
toDispose.Dispose();
}
}
}
}