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
5 changes: 3 additions & 2 deletions docs/content/compliance/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@ Each test sends a request that violates a specific **MUST** or **MUST NOT** requ
'COMP-POST-CL-UNDERSEND','COMP-CHUNKED-BODY','COMP-CHUNKED-MULTI',
'COMP-CHUNKED-EMPTY','COMP-CHUNKED-NO-FINAL',
'COMP-GET-WITH-CL-BODY','COMP-CHUNKED-EXTENSION',
'COMP-CHUNKED-TRAILER-VALID','COMP-CHUNKED-HEX-UPPERCASE'
'COMP-CHUNKED-TRAILER-VALID','COMP-CHUNKED-HEX-UPPERCASE',
'COMP-RANGE-POST'
]},
{ key: 'methods-upgrade', label: 'Methods & Upgrade', testIds: [
'COMP-METHOD-CONNECT',
'COMP-UNKNOWN-TE-501','COMP-EXPECT-UNKNOWN','COMP-METHOD-TRACE',
'COMP-TRACE-WITH-BODY',
'COMP-UPGRADE-POST','COMP-UPGRADE-MISSING-CONN',
'COMP-UPGRADE-UNKNOWN','COMP-UPGRADE-INVALID-VER',
'COMP-UPGRADE-UNKNOWN','COMP-UPGRADE-INVALID-VER','COMP-UPGRADE-HTTP10',
'COMP-CONNECTION-CLOSE','COMP-HTTP10-DEFAULT-CLOSE','COMP-HTTP10-NO-HOST'
]}
];
Expand Down
46 changes: 46 additions & 0 deletions docs/content/docs/body/range-post.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: "RANGE-POST"
description: "RANGE-POST test documentation"
weight: 13
---

| | |
|---|---|
| **Test ID** | `COMP-RANGE-POST` |
| **Category** | Compliance |
| **Scored** | Yes |
| **RFC** | [RFC 9110 §14.2](https://www.rfc-editor.org/rfc/rfc9110#section-14.2) |
| **RFC Level** | MUST |
| **Expected** | `2xx` (Range ignored) |

## What it sends

A POST request with a `Range` header. The Range mechanism only applies to GET requests.

```http
POST / HTTP/1.1\r\n
Host: localhost:8080\r\n
Content-Length: 5\r\n
Range: bytes=0-10\r\n
\r\n
hello
```

## What the RFC says

> "A server MUST ignore a Range header field received with a request method that is unrecognized or for which range handling is not defined." — RFC 9110 §14.2

Range handling is only defined for GET (RFC 9110 §14.2). For all other methods, the server must ignore the Range header and process the request normally.

## Why it matters

If a server incorrectly applies Range semantics to a POST request (returning `206 Partial Content`), it could truncate the request body or cause unexpected behavior. The server should process the full POST body and return a normal `2xx` response.

## Verdicts

- **Pass** — Server returns `2xx` (correctly ignored Range for POST)
- **Fail** — Server returns `206` (incorrectly applied Range to POST) or any non-2xx response

## Sources

- [RFC 9110 §14.2](https://www.rfc-editor.org/rfc/rfc9110#section-14.2)
47 changes: 47 additions & 0 deletions docs/content/docs/upgrade/upgrade-http10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: "UPGRADE-HTTP10"
description: "UPGRADE-HTTP10 test documentation"
weight: 5
---

| | |
|---|---|
| **Test ID** | `COMP-UPGRADE-HTTP10` |
| **Category** | Compliance |
| **Scored** | Yes |
| **RFC** | [RFC 9110 §7.8](https://www.rfc-editor.org/rfc/rfc9110#section-7.8) |
| **RFC Level** | MUST |
| **Expected** | Not `101` |

## What it sends

An HTTP/1.0 request with WebSocket upgrade headers. The server must ignore the Upgrade field because it was received in an HTTP/1.0 request.

```http
GET / HTTP/1.0\r\n
Host: localhost:8080\r\n
Connection: Upgrade\r\n
Upgrade: websocket\r\n
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n
Sec-WebSocket-Version: 13\r\n
\r\n
```

## What the RFC says

> "A server that receives an Upgrade header field in an HTTP/1.0 request MUST ignore that Upgrade field." — RFC 9110 §7.8

The Upgrade mechanism is an HTTP/1.1 feature. An HTTP/1.0 client cannot participate in protocol switching, so the server must not attempt it.

## Why it matters

If a server processes an Upgrade from an HTTP/1.0 client and returns `101 Switching Protocols`, the client likely cannot handle the protocol switch. This could lead to connection corruption or security issues, especially if a proxy is involved that speaks HTTP/1.0 to the backend.

## Verdicts

- **Pass** — Server returns any status other than `101` (correctly ignored Upgrade)
- **Fail** — Server returns `101 Switching Protocols` (incorrectly upgraded an HTTP/1.0 request)

## Sources

- [RFC 9110 §7.8](https://www.rfc-editor.org/rfc/rfc9110#section-7.8)
2 changes: 2 additions & 0 deletions docs/static/probe/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ window.ProbeRender = (function () {
'COMP-POST-NO-CL-NO-TE': '/Http11Probe/docs/body/post-no-cl-no-te/',
'COMP-UNKNOWN-METHOD': '/Http11Probe/docs/request-line/unknown-method/',
'COMP-UNKNOWN-TE-501': '/Http11Probe/docs/request-line/unknown-te-501/',
'COMP-RANGE-POST': '/Http11Probe/docs/body/range-post/',
'COMP-UPGRADE-HTTP10': '/Http11Probe/docs/upgrade/upgrade-http10/',
'COMP-UPGRADE-INVALID-VER': '/Http11Probe/docs/upgrade/upgrade-invalid-ver/',
'COMP-UPGRADE-MISSING-CONN': '/Http11Probe/docs/upgrade/upgrade-missing-conn/',
'COMP-UPGRADE-POST': '/Http11Probe/docs/upgrade/upgrade-post/',
Expand Down
48 changes: 48 additions & 0 deletions src/Http11Probe/TestCases/Suites/ComplianceSuite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,54 @@ public static IEnumerable<TestCase> GetTestCases()
}
};

// ── Range / Conditional ─────────────────────────────────────

yield return new TestCase
{
Id = "COMP-RANGE-POST",
Description = "Range header on POST must be ignored — Range only applies to GET",
Category = TestCategory.Compliance,
RfcReference = "RFC 9110 §14.2",
PayloadFactory = ctx => MakeRequest(
$"POST / HTTP/1.1\r\nHost: {ctx.HostHeader}\r\nContent-Length: 5\r\nRange: bytes=0-10\r\n\r\nhello"),
Expected = new ExpectedBehavior
{
Description = "2xx (Range ignored)",
CustomValidator = (response, state) =>
{
if (response is null)
return state == ConnectionState.ClosedByServer ? TestVerdict.Fail : TestVerdict.Fail;
if (response.StatusCode == 206)
return TestVerdict.Fail;
if (response.StatusCode is >= 200 and < 300)
return TestVerdict.Pass;
return TestVerdict.Fail;
}
}
};

yield return new TestCase
{
Id = "COMP-UPGRADE-HTTP10",
Description = "Upgrade header in HTTP/1.0 request must be ignored",
Category = TestCategory.Compliance,
RfcReference = "RFC 9110 §7.8",
PayloadFactory = ctx => MakeRequest(
$"GET / HTTP/1.0\r\nHost: {ctx.HostHeader}\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n"),
Expected = new ExpectedBehavior
{
Description = "!101",
CustomValidator = (response, state) =>
{
if (response is null)
return state == ConnectionState.ClosedByServer ? TestVerdict.Pass : TestVerdict.Fail;
if (response.StatusCode == 101)
return TestVerdict.Fail;
return TestVerdict.Pass;
}
}
};

// ── RFC 9110 response semantics ──────────────────────────────

yield return new TestCase
Expand Down
Loading