Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Http11Probe.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
<Project Path="src/Servers/SimpleWServer/SimpleWServer.csproj" />
<Project Path="src/Servers/SiskServer/SiskServer.csproj" />
<Project Path="src/Servers/ServiceStackServer/ServiceStackServer.csproj" />
<Project Path="src/Servers/EffinitiveServer/EffinitiveServer.csproj" />
</Folder>
</Solution>
172 changes: 172 additions & 0 deletions docs/content/servers/effinitive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: "Effinitive"
toc: false
breadcrumbs: false
---

**Language:** C# · [View source on GitHub](https://github.com/MDA2AV/Http11Probe/tree/main/src/Servers/EffinitiveServer)

## Dockerfile

```dockerfile
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY Directory.Build.props .
COPY src/Servers/EffinitiveServer/ src/Servers/EffinitiveServer/
RUN dotnet restore src/Servers/EffinitiveServer/EffinitiveServer.csproj
RUN dotnet publish src/Servers/EffinitiveServer/EffinitiveServer.csproj -c Release -o /app --no-restore

FROM mcr.microsoft.com/dotnet/runtime:10.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "EffinitiveServer.dll", "8080"]
```

## Source — `Program.cs`

```csharp
using System.Text;
using EffinitiveFramework.Core;
using EffinitiveFramework.Core.Http;

var port = args.Length > 0 && int.TryParse(args[0], out var p) ? p : 8080;

var app = EffinitiveApp
.Create()
.UsePort(port)
.MapEndpoints()
.Build();

Console.WriteLine($"Effinitive listening on http://localhost:{port}");
await app.RunAsync();

// ── GET / ──────────────────────────────────────────────────────

sealed class GetRoot : NoRequestEndpointBase<string>
{
protected override string Method => "GET";
protected override string Route => "/";
protected override string ContentType => "text/plain";

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult("OK");
Comment thread
HBartosch marked this conversation as resolved.
Outdated
}

// ── POST / ─────────────────────────────────────────────────────

sealed class PostRoot : NoRequestEndpointBase<string>
{
protected override string Method => "POST";
protected override string Route => "/";
protected override string ContentType => "text/plain";

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
{
var body = HttpContext?.Body;
return ValueTask.FromResult(body is { Length: > 0 } ? Encoding.UTF8.GetString(body) : "");
}
}

// ── GET/POST /echo ────────────────────────────────────────────

sealed class EchoGet : NoRequestEndpointBase<string>
{
protected override string Method => "GET";
protected override string Route => "/echo";
protected override string ContentType => "text/plain";

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.EchoHeaders(HttpContext));
}

sealed class EchoPost : NoRequestEndpointBase<string>
{
protected override string Method => "POST";
protected override string Route => "/echo";
protected override string ContentType => "text/plain";

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.EchoHeaders(HttpContext));
}

// ── GET/POST /cookie ──────────────────────────────────────────

sealed class CookieGet : NoRequestEndpointBase<string>
{
protected override string Method => "GET";
protected override string Route => "/cookie";
protected override string ContentType => "text/plain";

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.ParseCookies(HttpContext));
}

sealed class CookiePost : NoRequestEndpointBase<string>
{
protected override string Method => "POST";
protected override string Route => "/cookie";
protected override string ContentType => "text/plain";

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.ParseCookies(HttpContext));
}

// ── Shared helpers ────────────────────────────────────────────

static class Helpers
{
public static string EchoHeaders(HttpRequest? ctx)
{
if (ctx?.Headers is null) return "";
var sb = new StringBuilder();
foreach (var h in ctx.Headers)
sb.Append(h.Key).Append(": ").Append(h.Value).Append("\r\n");
return sb.ToString();
}

public static string ParseCookies(HttpRequest? ctx)
{
if (ctx is null) return "";
var sb = new StringBuilder();
foreach (var c in ctx.Cookies)
sb.Append(c.Key).Append('=').Append(c.Value).Append("\r\n");
return sb.ToString();
}
}
```

## Test Results

<div id="server-summary"><p><em>Loading results...</em></p></div>

### Compliance

<div id="results-compliance"></div>

### Smuggling

<div id="results-smuggling"></div>

### Malformed Input

<div id="results-malformedinput"></div>

### Caching

<div id="results-capabilities"></div>

### Cookies

<div id="results-cookies"></div>

<script src="/probe/data.js"></script>
<script src="/probe/render.js"></script>
<script>
(function() {
if (!window.PROBE_DATA) {
document.getElementById('server-summary').innerHTML = '<p><em>No probe data available yet. Run the Probe workflow on <code>main</code> to generate results.</em></p>';
return;
}
ProbeRender.renderServerPage('Effinitive');
})();
</script>
11 changes: 11 additions & 0 deletions src/Servers/EffinitiveServer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY Directory.Build.props .
COPY src/Servers/EffinitiveServer/ src/Servers/EffinitiveServer/
RUN dotnet restore src/Servers/EffinitiveServer/EffinitiveServer.csproj
RUN dotnet publish src/Servers/EffinitiveServer/EffinitiveServer.csproj -c Release -o /app --no-restore

FROM mcr.microsoft.com/dotnet/runtime:10.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "EffinitiveServer.dll", "8080"]
13 changes: 13 additions & 0 deletions src/Servers/EffinitiveServer/EffinitiveServer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="EffinitiveFramework.Core" Version="1.3.*" />
Comment thread
HBartosch marked this conversation as resolved.
Outdated
</ItemGroup>

</Project>
114 changes: 114 additions & 0 deletions src/Servers/EffinitiveServer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Text;
using EffinitiveFramework.Core;
using EffinitiveFramework.Core.Http;
using EffinitiveServer.Endpoints;
Comment thread
HBartosch marked this conversation as resolved.
Outdated

var port = args.Length > 0 && int.TryParse(args[0], out var p) ? p : 8080;

var app = EffinitiveApp
.Create()
.UsePort(port)
.MapEndpoints()
.Build();

Console.WriteLine($"Effinitive listening on http://localhost:{port}");
await app.RunAsync();

namespace EffinitiveServer.Endpoints
{
// ── GET / ──────────────────────────────────────────────────────

sealed class GetRoot : NoRequestEndpointBase<string>
{
protected override string Method => "GET";
protected override string Route => "/";
protected override string ContentType => Helpers.TextPlain;

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult("OK");
}

// ── POST / ─────────────────────────────────────────────────────

sealed class PostRoot : NoRequestEndpointBase<string>
{
protected override string Method => "POST";
protected override string Route => "/";
protected override string ContentType => Helpers.TextPlain;

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
{
var body = HttpContext?.Body;
return ValueTask.FromResult(body is { Length: > 0 } ? Encoding.UTF8.GetString(body) : "");
}
}

// ── GET/POST /echo ────────────────────────────────────────────

sealed class EchoGet : NoRequestEndpointBase<string>
{
protected override string Method => "GET";
protected override string Route => "/echo";
protected override string ContentType => Helpers.TextPlain;

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.EchoHeaders(HttpContext));
}

sealed class EchoPost : NoRequestEndpointBase<string>
{
protected override string Method => "POST";
protected override string Route => "/echo";
protected override string ContentType => Helpers.TextPlain;

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.EchoHeaders(HttpContext));
}

// ── GET/POST /cookie ──────────────────────────────────────────

sealed class CookieGet : NoRequestEndpointBase<string>
{
protected override string Method => "GET";
protected override string Route => "/cookie";
protected override string ContentType => Helpers.TextPlain;

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.ParseCookies(HttpContext));
}

sealed class CookiePost : NoRequestEndpointBase<string>
{
protected override string Method => "POST";
protected override string Route => "/cookie";
protected override string ContentType => Helpers.TextPlain;

public override ValueTask<string> HandleAsync(CancellationToken ct = default)
=> ValueTask.FromResult(Helpers.ParseCookies(HttpContext));
}

// ── Shared helpers ────────────────────────────────────────────

static class Helpers
{
public const string TextPlain = "text/plain";

public static string EchoHeaders(HttpRequest? ctx)
{
if (ctx?.Headers is null) return "";
var sb = new StringBuilder();
foreach (var h in ctx.Headers)
sb.Append(h.Key).Append(": ").Append(h.Value).Append("\r\n");
return sb.ToString();
}

public static string ParseCookies(HttpRequest? ctx)
{
if (ctx is null) return "";
var sb = new StringBuilder();
foreach (var c in ctx.Cookies)
sb.Append(c.Key).Append('=').Append(c.Value).Append("\r\n");
return sb.ToString();
}
}
}
1 change: 1 addition & 0 deletions src/Servers/EffinitiveServer/probe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name": "Effinitive", "language": "C#"}
Loading