Files

93 lines
2.6 KiB
C#
Raw Permalink Normal View History

2024-01-04 16:27:14 +00:00
using System.Net;
2014-07-28 10:53:28 +02:00
using System.Text;
2024-09-21 12:48:05 -06:00
using Velopack.Util;
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
namespace Velopack.Tests;
public sealed class StaticHttpServer : IDisposable
2014-07-28 10:53:28 +02:00
{
2024-02-02 12:26:31 +00:00
public int Port { get; private set; }
public string RootPath { get; private set; }
IDisposable inner;
public StaticHttpServer(int port, string rootPath)
2014-07-28 10:53:28 +02:00
{
2024-02-02 12:26:31 +00:00
Port = port; RootPath = rootPath;
}
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
public IDisposable Start()
{
if (inner != null) {
throw new InvalidOperationException("Already started!");
2014-07-28 10:53:28 +02:00
}
2024-02-02 12:26:31 +00:00
var server = new HttpListener();
server.Prefixes.Add(String.Format("http://+:{0}/", Port));
server.Start();
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
bool shouldStop = false;
var listener = Task.Run(async () => {
while (!shouldStop) {
var ctx = await server.GetContextAsync();
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
if (ctx.Request.HttpMethod != "GET") {
closeResponseWith(ctx, 400, "GETs only");
return;
2014-07-28 11:12:14 +02:00
}
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
var target = Path.Combine(RootPath, ctx.Request.Url.AbsolutePath.Replace('/', Path.DirectorySeparatorChar).Substring(1));
var fi = new FileInfo(target);
2014-07-28 11:12:14 +02:00
2024-02-02 12:26:31 +00:00
if (!fi.FullName.StartsWith(RootPath)) {
closeResponseWith(ctx, 401, "Not authorized");
return;
}
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
if (!fi.Exists) {
closeResponseWith(ctx, 404, "Not found");
return;
}
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
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 10:53:28 +02:00
}
2024-02-02 12:26:31 +00:00
});
2014-07-28 10:53:28 +02:00
2024-02-02 12:26:31 +00:00
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();
2014-07-28 10:53:28 +02:00
}
}
}