mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
93 lines
2.8 KiB
C#
93 lines
2.8 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
|
|
namespace Velopack.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();
|
|
|
|
bool shouldStop = false;
|
|
var listener = Task.Run(async () => {
|
|
while (!shouldStop) {
|
|
var ctx = await server.GetContextAsync();
|
|
|
|
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());
|
|
}
|
|
}
|
|
});
|
|
|
|
var ret = Disposable.Create(() => {
|
|
shouldStop = true;
|
|
server.Stop();
|
|
listener.Wait(2000);
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
}
|