namespace DTLib.Web.Routes; public class ServeFilesRouteHandler(IOPath _publicDir, string _homePageUrl = "index.html") : IRouteHandler { public async Task HandleRequest(HttpListenerContext ctx) { if (ctx.Request.HttpMethod != "GET") return HttpStatusCode.BadRequest; string requestPath = ctx.Request.Url?.AbsolutePath!; if (string.IsNullOrEmpty(requestPath) || requestPath == "/") { requestPath = _homePageUrl; } string ext = Path.Extension(requestPath).Str; IOPath filePath = Path.Concat(_publicDir, requestPath); if (!File.Exists(filePath)) return HttpStatusCode.NotFound; List<(string key, string val)> headers = ext switch { "html" => [("Content-Type", "text/html")], "css" => [("Content-Type", "text/css")], "js" or "jsx" or "ts" or "tsx" or "map" => [("Content-Type", "text/javascript")], _ => [ ("Content-Type", "binary/octet-stream"), ("Content-Disposition", $"attachment filename={filePath.LastName()}") ] }; foreach (var header in headers) ctx.Response.Headers.Set(header.key, header.val); var fileStream = File.OpenRead(filePath); ctx.Response.ContentLength64 = fileStream.Length; await fileStream.CopyToAsync(ctx.Response.OutputStream); return HttpStatusCode.OK; } }