From b3bb9c70e72d922bc484b71b09427bbe788a29dc Mon Sep 17 00:00:00 2001 From: Diogo Martins Date: Sat, 14 Feb 2026 22:05:14 +0000 Subject: [PATCH] Add FastEndpoints framework --- Http11Probe.slnx | 1 + docs/content/servers/fastendpoints.md | 150 ++++++++++++++++++ docs/static/probe/render.js | 1 + src/Servers/FastEndpointsServer/Dockerfile | 11 ++ .../FastEndpointsServer.csproj | 14 ++ src/Servers/FastEndpointsServer/Program.cs | 103 ++++++++++++ src/Servers/FastEndpointsServer/probe.json | 1 + 7 files changed, 281 insertions(+) create mode 100644 docs/content/servers/fastendpoints.md create mode 100644 src/Servers/FastEndpointsServer/Dockerfile create mode 100644 src/Servers/FastEndpointsServer/FastEndpointsServer.csproj create mode 100644 src/Servers/FastEndpointsServer/Program.cs create mode 100644 src/Servers/FastEndpointsServer/probe.json diff --git a/Http11Probe.slnx b/Http11Probe.slnx index a97cded..087fde1 100644 --- a/Http11Probe.slnx +++ b/Http11Probe.slnx @@ -6,6 +6,7 @@ + diff --git a/docs/content/servers/fastendpoints.md b/docs/content/servers/fastendpoints.md new file mode 100644 index 0000000..c56352b --- /dev/null +++ b/docs/content/servers/fastendpoints.md @@ -0,0 +1,150 @@ +--- +title: "FastEndpoints" +toc: false +breadcrumbs: false +--- + +**Language:** C# · [View source on GitHub](https://github.com/MDA2AV/Http11Probe/tree/main/src/Servers/FastEndpointsServer) + +## Dockerfile + +```dockerfile +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY Directory.Build.props . +COPY src/Servers/FastEndpointsServer/ src/Servers/FastEndpointsServer/ +RUN dotnet restore src/Servers/FastEndpointsServer/FastEndpointsServer.csproj +RUN dotnet publish src/Servers/FastEndpointsServer/FastEndpointsServer.csproj -c Release -o /app --no-restore + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 +WORKDIR /app +COPY --from=build /app . +ENTRYPOINT ["dotnet", "FastEndpointsServer.dll"] +``` + +## Source — `Program.cs` + +```csharp +using FastEndpoints; + +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.UseUrls("http://+:8080"); +builder.Services.AddFastEndpoints(o => o.Assemblies = [typeof(GetRoot).Assembly]); + +var app = builder.Build(); + +app.UseFastEndpoints(); + +app.Run(); + +// ── GET / ────────────────────────────────────────────────────── + +sealed class GetRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Get("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + await HttpContext.Response.WriteAsync("OK", ct); + } +} + +// ── HEAD / ───────────────────────────────────────────────────── + +sealed class HeadRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Verbs("HEAD"); + Routes("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + HttpContext.Response.StatusCode = 200; + await HttpContext.Response.WriteAsync("", ct); + } +} + +// ── POST / ───────────────────────────────────────────────────── + +sealed class PostRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Post("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + using var reader = new StreamReader(HttpContext.Request.Body); + var body = await reader.ReadToEndAsync(ct); + await HttpContext.Response.WriteAsync(body, ct); + } +} + +// ── OPTIONS / ────────────────────────────────────────────────── + +sealed class OptionsRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Verbs("OPTIONS"); + Routes("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + HttpContext.Response.Headers["Allow"] = "GET, HEAD, POST, OPTIONS"; + HttpContext.Response.StatusCode = 200; + await HttpContext.Response.WriteAsync("", ct); + } +} + +// ── POST /echo ───────────────────────────────────────────────── + +sealed class PostEcho : EndpointWithoutRequest +{ + public override void Configure() + { + Post("/echo"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var sb = new System.Text.StringBuilder(); + foreach (var h in HttpContext.Request.Headers) + foreach (var v in h.Value) + sb.AppendLine($"{h.Key}: {v}"); + await HttpContext.Response.WriteAsync(sb.ToString(), ct); + } +} +``` + +## Source — `FastEndpointsServer.csproj` + +```xml + + + + net10.0 + enable + enable + false + + + + + + + +``` diff --git a/docs/static/probe/render.js b/docs/static/probe/render.js index c8dfa0c..eb5cc85 100644 --- a/docs/static/probe/render.js +++ b/docs/static/probe/render.js @@ -404,6 +404,7 @@ window.ProbeRender = (function () { 'EmbedIO': '/Http11Probe/servers/embedio/', 'Envoy': '/Http11Probe/servers/envoy/', 'Express': '/Http11Probe/servers/express/', + 'FastEndpoints': '/Http11Probe/servers/fastendpoints/', 'FastHTTP': '/Http11Probe/servers/fasthttp/', 'Flask': '/Http11Probe/servers/flask/', 'GenHTTP': '/Http11Probe/servers/genhttp/', diff --git a/src/Servers/FastEndpointsServer/Dockerfile b/src/Servers/FastEndpointsServer/Dockerfile new file mode 100644 index 0000000..5ac650e --- /dev/null +++ b/src/Servers/FastEndpointsServer/Dockerfile @@ -0,0 +1,11 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY Directory.Build.props . +COPY src/Servers/FastEndpointsServer/ src/Servers/FastEndpointsServer/ +RUN dotnet restore src/Servers/FastEndpointsServer/FastEndpointsServer.csproj +RUN dotnet publish src/Servers/FastEndpointsServer/FastEndpointsServer.csproj -c Release -o /app --no-restore + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 +WORKDIR /app +COPY --from=build /app . +ENTRYPOINT ["dotnet", "FastEndpointsServer.dll"] diff --git a/src/Servers/FastEndpointsServer/FastEndpointsServer.csproj b/src/Servers/FastEndpointsServer/FastEndpointsServer.csproj new file mode 100644 index 0000000..f4854c8 --- /dev/null +++ b/src/Servers/FastEndpointsServer/FastEndpointsServer.csproj @@ -0,0 +1,14 @@ + + + + net10.0 + enable + enable + false + + + + + + + diff --git a/src/Servers/FastEndpointsServer/Program.cs b/src/Servers/FastEndpointsServer/Program.cs new file mode 100644 index 0000000..6a01f3f --- /dev/null +++ b/src/Servers/FastEndpointsServer/Program.cs @@ -0,0 +1,103 @@ +using FastEndpoints; + +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.UseUrls("http://+:8080"); +builder.Services.AddFastEndpoints(o => o.Assemblies = [typeof(GetRoot).Assembly]); + +var app = builder.Build(); + +app.UseFastEndpoints(); + +app.Run(); + +// ── GET / ────────────────────────────────────────────────────── + +sealed class GetRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Get("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + await HttpContext.Response.WriteAsync("OK", ct); + } +} + +// ── HEAD / ───────────────────────────────────────────────────── + +sealed class HeadRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Verbs("HEAD"); + Routes("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + HttpContext.Response.StatusCode = 200; + await HttpContext.Response.WriteAsync("", ct); + } +} + +// ── POST / ───────────────────────────────────────────────────── + +sealed class PostRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Post("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + using var reader = new StreamReader(HttpContext.Request.Body); + var body = await reader.ReadToEndAsync(ct); + await HttpContext.Response.WriteAsync(body, ct); + } +} + +// ── OPTIONS / ────────────────────────────────────────────────── + +sealed class OptionsRoot : EndpointWithoutRequest +{ + public override void Configure() + { + Verbs("OPTIONS"); + Routes("/"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + HttpContext.Response.Headers["Allow"] = "GET, HEAD, POST, OPTIONS"; + HttpContext.Response.StatusCode = 200; + await HttpContext.Response.WriteAsync("", ct); + } +} + +// ── POST /echo ───────────────────────────────────────────────── + +sealed class PostEcho : EndpointWithoutRequest +{ + public override void Configure() + { + Post("/echo"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var sb = new System.Text.StringBuilder(); + foreach (var h in HttpContext.Request.Headers) + foreach (var v in h.Value) + sb.AppendLine($"{h.Key}: {v}"); + await HttpContext.Response.WriteAsync(sb.ToString(), ct); + } +} diff --git a/src/Servers/FastEndpointsServer/probe.json b/src/Servers/FastEndpointsServer/probe.json new file mode 100644 index 0000000..8005998 --- /dev/null +++ b/src/Servers/FastEndpointsServer/probe.json @@ -0,0 +1 @@ +{"name": "FastEndpoints", "language": "C#"}