Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ All notable changes to Http11Probe are documented in this file.
- **Row-click detail popup** — clicking a server row opens a modal showing that server's results for the current table in a vertical layout (Test, Expected, Got, Description) with section and table name in the header
- **Truncation notice** — tooltip and modal now show a `[Truncated]` notice at the top when raw request/response data exceeds the 8,192-byte display limit
- **Filter box** — text input above result tables to filter by server name, language, or test name; supports multiple comma-separated keywords
- **`--verbose` CLI flag** — prints the raw server response below each test result when enabled (`--verbose` or `-v`)

### Changed
- **Horizontal column headers** — test name headers are now displayed horizontally instead of rotated at -55°, improving readability
Expand All @@ -31,6 +32,7 @@ All notable changes to Http11Probe are documented in this file.
- **Stronger sticky shadow on mobile** — increased shadow intensity for the pinned server name column
- **Scrollable tooltips** — hover tooltips are now interactive and scrollable for large payloads (removed `pointer-events:none`, increased `max-height` to `60vh`)
- **Larger click modal** — expanded from `max-width:700px` to `90vw` and `max-height` from `80vh` to `85vh` to better accommodate large request/response data
- **Kestrel HEAD/OPTIONS support** — added explicit HEAD and OPTIONS endpoint handlers to ASP.NET Minimal server so smuggling tests evaluate correctly instead of returning 405
- Raw request capture now includes truncation metadata when payload exceeds 8,192 bytes (`TestRunner.cs`)
- Raw response capture now includes truncation metadata when response exceeds 8,192 bytes (`ResponseParser.cs`)

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dotnet run --project src/Http11Probe.Cli -- --host localhost --port 8080
| `--test` | Run only specific test IDs, case-insensitive (repeatable) | all |
| `--timeout` | Connect and read timeout in seconds per test | `5` |
| `--output` | Write JSON results to file | — |
| `--verbose`, `-v` | Print the raw server response for each test | off |

### Examples

Expand Down
14 changes: 12 additions & 2 deletions src/Http11Probe.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@

var outputOption = new Option<string?>("--output") { Description = "Write JSON results to this file path" };

var verboseOption = new Option<bool>("--verbose", "-v") { Description = "Print the raw server response for each test" };
verboseOption.DefaultValueFactory = _ => false;

var rootCommand = new RootCommand("Http11Probe — HTTP/1.1 server compliance & hardening tester")
{
hostOption,
portOption,
categoryOption,
testOption,
timeoutOption,
outputOption
outputOption,
verboseOption
};

rootCommand.SetAction(async (parseResult, cancellationToken) =>
Expand All @@ -37,6 +41,7 @@
var timeout = parseResult.GetValue(timeoutOption);
var testIds = parseResult.GetValue(testOption);
var outputPath = parseResult.GetValue(outputOption);
var verbose = parseResult.GetValue(verboseOption);

Console.WriteLine($" Http11Probe targeting {host}:{port}");
Console.WriteLine();
Expand All @@ -62,7 +67,12 @@
var runner = new TestRunner(options);

ConsoleReporter.PrintHeader();
var report = await runner.RunAsync(testCases, ConsoleReporter.PrintRow);
var report = await runner.RunAsync(testCases, result =>
{
ConsoleReporter.PrintRow(result);
if (verbose)
ConsoleReporter.PrintRawResponse(result);
});
ConsoleReporter.PrintSummary(report);

if (outputPath is not null)
Expand Down
21 changes: 21 additions & 0 deletions src/Http11Probe.Cli/Reporting/ConsoleReporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,27 @@ public static void PrintRow(TestResult result)
Console.WriteLine();
}

public static void PrintRawResponse(TestResult result)
{
if (result.Verdict == TestVerdict.Skip)
return;

var raw = result.Response?.RawResponse;
if (raw is null)
{
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine(" (no response)");
Console.ResetColor();
return;
}

Console.ForegroundColor = ConsoleColor.DarkGray;
foreach (var line in raw.Split('\n'))
Console.WriteLine($" {line.TrimEnd('\r')}");
Console.ResetColor();
Console.WriteLine();
}

public static void PrintSummary(TestRunReport report)
{
Console.WriteLine(" " + new string('─', 80));
Expand Down
8 changes: 8 additions & 0 deletions src/Servers/AspNetMinimal/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

app.MapGet("/", () => "OK");

app.MapMethods("/", ["HEAD"], () => Results.Ok());

app.MapMethods("/", ["OPTIONS"], (HttpContext ctx) =>
{
ctx.Response.Headers["Allow"] = "GET, HEAD, POST, OPTIONS";
return Results.Ok();
});

app.MapPost("/", async (HttpContext ctx) =>
{
using var reader = new StreamReader(ctx.Request.Body);
Expand Down
Loading