Last active
March 2, 2025 14:27
-
-
Save flq/39c7feba1061d6a2dca72dfc2d3dd419 to your computer and use it in GitHub Desktop.
The minimal file server written by ChatGPT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Builder; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.AspNetCore.StaticFiles; | |
using Microsoft.Extensions.Hosting; | |
using System; | |
using System.IO; | |
using System.Linq; | |
using System.Text.Encodings.Web; | |
using System.Threading.Tasks; | |
if (args.Length == 0 || !Directory.Exists(args[0])) | |
{ | |
Console.WriteLine("Usage: dotnet run <root-path>"); | |
return; | |
} | |
string rootPath = Path.GetFullPath(args[0]); | |
var contentTypeProvider = new FileExtensionContentTypeProvider(); | |
var builder = WebApplication.CreateBuilder(); | |
var app = builder.Build(); | |
app.MapGet("/{**path}", (HttpContext context, string? path) => | |
{ | |
string requestedPath = path ?? ""; | |
string fullPath = Path.Combine(rootPath, requestedPath); | |
if (!fullPath.StartsWith(rootPath)) // Prevent directory traversal | |
{ | |
return Results.Forbid(); | |
} | |
if (Directory.Exists(fullPath)) | |
{ | |
var entries = Directory.EnumerateFileSystemEntries(fullPath) | |
.Select(entry => | |
{ | |
string name = Path.GetFileName(entry); | |
string encodedName = HtmlEncoder.Default.Encode(name); | |
string relativePath = Path.Combine(requestedPath, name).Replace("\\", "/"); | |
return $"<li><a href='/{relativePath}'>{encodedName}{(Directory.Exists(entry) ? "/" : "")}</a></li>"; | |
}); | |
string responseHtml = $""" | |
<html> | |
<body> | |
<h1>Index of /{HtmlEncoder.Default.Encode(requestedPath)}</h1> | |
<ul> | |
{string.Join("", entries)} | |
</ul> | |
</body> | |
</html> | |
"""; | |
return Results.Content(responseHtml, "text/html"); | |
} | |
else if (File.Exists(fullPath)) | |
{ | |
string contentType = contentTypeProvider.TryGetContentType(fullPath, out var mimeType) ? mimeType! : "application/octet-stream"; | |
return Results.File(fullPath, contentType, Path.GetFileName(fullPath)); | |
} | |
else | |
{ | |
return Results.NotFound("Not Found"); | |
} | |
}); | |
await app.RunAsync(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment