Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
7961e23
chore(Servus.Akka): fix whitespace and formatting
st0o0 May 16, 2026
509dbe8
fix(Servus.Akka): use async dispose and cancellation
st0o0 May 16, 2026
25e4021
ci: restrict CodeQL analysis to main branch
st0o0 May 16, 2026
bbf8f14
docs: update CLAUDE.md for server project and code style rules
st0o0 May 16, 2026
258c69d
chore: remove ARCHITECTURE.md
st0o0 May 16, 2026
f07f8d4
refactor(TurboHTTP): restructure protocol to LineBased/Multiplexed ar…
st0o0 May 16, 2026
683bbbb
feat(TurboHTTP.Server): add Akka.Streams-based HTTP server
st0o0 May 16, 2026
fb51ed0
refactor(tests): update shared test infrastructure for server support
st0o0 May 16, 2026
d5b8872
refactor(tests): restructure tests to match new protocol architecture
st0o0 May 16, 2026
e24f7af
chore(protocol): normalize formatting across H2 and H3 protocol layers
st0o0 May 16, 2026
8b05a70
refactor(multiplexed): make StreamBodyMessages generic for type-safe …
st0o0 May 16, 2026
3896efb
refactor(http3): delegate client body encoding to Multiplexed BodyEnc…
st0o0 May 16, 2026
2d0181e
chore: apply formatter across codebase
st0o0 May 16, 2026
2526f67
refactor(tests): remove CtsPoolSpec that only tested .NET framework b…
st0o0 May 16, 2026
99462ef
refactor(tests): move TransportBufferPoolSpec to Servus.Akka.Tests
st0o0 May 16, 2026
da96383
refactor(tests): migrate EngineTestBase from static ActorSystem to St…
st0o0 May 16, 2026
78ccb24
refactor(tests): migrate stream stage tests to StreamTestBase
st0o0 May 16, 2026
1769c4a
refactor(tests): migrate StateMachine and factory tests to TestKit
st0o0 May 16, 2026
f61048c
refactor(tests): restructure Http2 tests into Client/Server hierarchy
st0o0 May 16, 2026
36a71c9
refactor(tests): restructure Http3 tests into Client/Server hierarchy
st0o0 May 16, 2026
c536296
docs: add planning documents and update CLAUDE.md
st0o0 May 18, 2026
5743e36
feat(semantics): add RFC-compliant HTTP semantic validators
st0o0 May 18, 2026
9031795
refactor(tests): reorganize Semantics tests into domain subfolders
st0o0 May 18, 2026
3138c12
feat(protocol): extract encoder/decoder options for HTTP/2 and HTTP/3
st0o0 May 18, 2026
40eddab
refactor(protocol): improve HTTP/1.x and line-based protocol layer
st0o0 May 18, 2026
9d23973
refactor(protocol): improve HTTP/2 protocol layer and restructure tests
st0o0 May 18, 2026
771503d
refactor(protocol): improve HTTP/3 and multiplexed protocol layer
st0o0 May 18, 2026
b3e5e32
refactor(streams): update stream stages, lifecycle, and rename tests
st0o0 May 18, 2026
fd275b8
refactor(integration): overhaul test infrastructure with backend abst…
st0o0 May 18, 2026
7884dbb
refactor(tests): update acceptance tests and shared test helpers
st0o0 May 18, 2026
35ece94
chore: update license copyright holder to leberkas-org
st0o0 May 19, 2026
22c633e
docs: remove completed planning documents
st0o0 May 19, 2026
ffbaa36
fix(transport): make TLS handshake async with configurable timeout
st0o0 May 19, 2026
9aec826
feat(streams): add Pipe stages for bidirectional IO bridging
st0o0 May 19, 2026
d52d45d
refactor(client): add version-guarded exception signaling and remove …
st0o0 May 19, 2026
a4ca9c2
refactor(protocol): harden server encoders and improve redirect handling
st0o0 May 19, 2026
3eef5b4
test(protocol): add server-side security and hardening specs
st0o0 May 19, 2026
196c05b
feat(server): implement entity gateway with ASP.NET-style middleware …
st0o0 May 19, 2026
5f7c346
test(server): add unit tests for server components
st0o0 May 19, 2026
92708bc
test(integration): expand test infrastructure and add server integrat…
st0o0 May 19, 2026
e336851
test(api): update API approval surface for server additions
st0o0 May 19, 2026
7fb64b9
chore(server): mark TurboHTTP.Server as non-packable
st0o0 May 19, 2026
fe64ec4
refactor: merge TurboHTTP.Server into TurboHTTP and reorganize client…
st0o0 May 19, 2026
4d88f62
test: update all test projects for merged namespace structure
st0o0 May 19, 2026
cf6c0d4
test(api): consolidate API approval into single assembly snapshot
st0o0 May 19, 2026
08d0809
docs: restructure documentation into client and server sections
st0o0 May 19, 2026
b8471e5
chore: update CLAUDE.md architecture section for merged project
st0o0 May 19, 2026
99a3a6a
refactor(server): simplify entity routing and move builder types into…
st0o0 May 19, 2026
cd14802
test(server): remove obsolete RegistryResolverSpec and update entity …
st0o0 May 19, 2026
37cc531
test: improve test quality with CancellationToken propagation and mod…
st0o0 May 19, 2026
8a0189b
test(api): update API snapshot for entity routing simplification
st0o0 May 19, 2026
81669f8
docs: Update GitHub repository link
st0o0 May 19, 2026
6afcfd6
fix(security): address CodeQL findings for cookie injection and open …
st0o0 May 19, 2026
28c81d8
fix: EntityDispatcher tests
st0o0 May 19, 2026
2560a4a
fix(test): generate HTTPS test certificate programmatically
st0o0 May 19, 2026
1174fa6
fix(security): sanitize response header values in test httpbin endpoint
st0o0 May 19, 2026
178c966
fix: resolve H11 POST redirect deadlock and enable skipped acceptance…
st0o0 May 19, 2026
d119a05
fix(security): reject CRLF and normalize URLs in TurboHttpResponse.Re…
st0o0 May 19, 2026
4b1d390
fix(security): prevent open redirect in HandleRedirectTo and harden R…
st0o0 May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ name: "CodeQL"

on:
push:
branches: [ "main", feature/*, ]
branches: [ "main" ]
paths:
- "src/**/*.cs"
- "src/**/*.csproj"
Expand Down Expand Up @@ -82,4 +82,4 @@ jobs:
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
category: "/language:${{matrix.language}}"
335 changes: 0 additions & 335 deletions ARCHITECTURE.md

This file was deleted.

82 changes: 49 additions & 33 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
# CLAUDE.md

High-performance HTTP client for .NET built on Akka.Streams. Implements HTTP/1.0, 1.1, 2, 3 (QUIC) with full RFC compliance.
High-performance HTTP client and server for .NET built on Akka.Streams. Implements HTTP/1.0, 1.1, 2, 3 (QUIC) with full RFC compliance.

## Build & Test

All commands run from `src/` (where `global.json` lives). Restore/build use full paths from repo root.
All commands run from `src/` (where `global.json` lives).

```bash
dotnet restore ./src/TurboHTTP.slnx
dotnet build --configuration Release ./src/TurboHTTP.slnx
dotnet restore TurboHTTP.slnx
dotnet build --configuration Release TurboHTTP.slnx

# Tests (xUnit v3 direct runner)
dotnet test --project TurboHTTP.Tests/TurboHTTP.Tests.csproj # unit + stage
dotnet test --project TurboHTTP.IntegrationTests/TurboHTTP.IntegrationTests.csproj # integration (network)
# Tests (xUnit v3 — use dotnet run, not dotnet test)
dotnet run --project TurboHTTP.Tests/TurboHTTP.Tests.csproj # all unit + stage
dotnet run --project TurboHTTP.IntegrationTests/TurboHTTP.IntegrationTests.csproj # integration (network)

# Single class (preferred for integration — full suite is slow)
dotnet run --project TurboHTTP.IntegrationTests/TurboHTTP.IntegrationTests.csproj -- -class "TurboHTTP.IntegrationTests.H2.ConnectionSpec"

# Single method / namespace
dotnet run --project TurboHTTP.Tests/TurboHTTP.Tests.csproj -- -namespace "TurboHTTP.Tests.RFC9113"
dotnet run --project TurboHTTP.Tests/TurboHTTP.Tests.csproj -- -class "TurboHTTP.Tests.RFC9113.Http2DecoderErrorCodeTests"
# Single class / filter
dotnet run --project TurboHTTP.Tests/TurboHTTP.Tests.csproj -- -class "TurboHTTP.Tests.Protocol.Syntax.Http2.Frames.Http2DecoderErrorCodeSpec"

# Integration tests with specific backend (default: auto-detect Docker, fallback Kestrel)
$env:TURBOHTTP_TEST_BACKEND = "kestrel" # force Kestrel (no Docker needed)
$env:TURBOHTTP_TEST_BACKEND = "docker" # force Docker (fails if unavailable)

# Benchmarks
dotnet run --configuration Release --project TurboHTTP.Benchmarks/TurboHTTP.Benchmarks.csproj

# Docs site (Node.js 20+)
cd docs && npm install && npm run docs:dev
cd ../docs && npm install && npm run docs:dev
```

## Architecture

```
Client Surface (TurboHTTP/) — ITurboHttpClient, factory, builder, DI
Streams Layer (TurboHTTP/Streams/) — Engines (Http10/11/20/30Engine), Stages/{Encoding,Decoding,Features,Routing}
Protocol Layer (TurboHTTP/Protocol/) — Http10/, Http11/, Http2/, Http3/, Cookies/, Caching/, Semantics/, AltSvc/
Transport Layer (TurboHTTP/Transport/) — Connection/, Tcp/, Quic/
Client Surface (TurboHTTP/Client/) - ITurboHttpClient, factory, builder, DI, options
Server Surface (TurboHTTP/Server/) - TurboServerOptions, TurboHttpContext, Context/
Server Domains (TurboHTTP/Server/{domain}/) - Middleware, Routing, Binding, Entity, Hosting, Lifecycle
Streams Layer (TurboHTTP/Streams/) - Engines, Stages/{Client,Server,Features,Internal}
Protocol Layer (TurboHTTP/Protocol/) - Http10/, Http11/, Http2/, Http3/, Semantics/
Features (TurboHTTP/Features/) - Cookies/, Caching/, AltSvc/
```

## Obsidian Vault (`notes/`)

Single source of truth for all non-code knowledge. **Use Obsidian MCP tools** (`search_notes`, `read_note`, `write_note`, `patch_note`) — never `Read`/`Write`/`Edit` on `notes/` files.

- Before RFC work → `search_notes("RFC XXXX")`
- Before architecture decisions → `search_notes("component name")`
- Before ending a session → write discoveries via `write_note` or `patch_note`

### RFC vault structure

Expand All @@ -53,7 +56,6 @@ Single source of truth for all non-code knowledge. **Use Obsidian MCP tools** (`

- **Do NOT commit** unless the user explicitly asks
- **Always respond in English** regardless of input language
- **Write discoveries to Obsidian** after every session

## Code Style

Expand All @@ -65,11 +67,12 @@ Single source of truth for all non-code knowledge. **Use Obsidian MCP tools** (`
- No decorative separator comments (`// ───`, `// ===`, `// ---` section dividers)
- Allman braces, 4 spaces, `_fieldName` for private fields
- `var` when type is apparent, `sealed` by default
- No `#nullable enable` (project-level), no `async void` / `.Result` / `.Wait()`
- No `#nullable enable` (project-level), no `async void` / `.Result` / `.Wait()` / `.GetAwaiter().GetResult()`
- Always pass `CancellationToken`, always use braces (even single-line)
- `Task<T>` not Future, `TimeSpan` not Duration
- Extend-only public APIs, preserve wire format compatibility
- Include unit tests with all changes
- **Size literals**: Always `N * 1024` or `N * 1024 * 1024`, never raw numbers like `65536` or `2_097_152`

## Performance Patterns

Expand All @@ -92,6 +95,31 @@ New tests use **component-based folders** (`Http10/`, `Http11/`, `Http2/`, etc.)
- `[Fact(DisplayName = ...)]` is deprecated — method name IS the documentation
- Max 500 lines per test class

### Test File Naming Convention

**File name = class name, always.** Pattern: `{ProtocolPrefix?}{ProductionClassName}{TestConcern?}Spec`

- Protocol prefix (`Http2`, `Http3`, `Hpack`, `Qpack`) required when test is under `Protocol/Syntax/{HttpVersion}/` or class name is shared across namespaces
- Omit prefix when class is globally unique (`CookieJar`, `CacheStore`) or in protocol-agnostic folders (`Client/`, `Features/`)
- When a SUT has multiple test files, suffix describes **test concern** — never `Part1`/`Part2`/numbered
- Duplicates disambiguated by test focus, not location

### H2/H3 Test Folder Placement

| Folder | What belongs here | Types under test |
|--------|------------------|-----------------|
| **Frames/** | Wire format: serialize, deserialize, parse, validate | `FrameDecoder`, `Http2Frame`/`Http3Frame` subtypes |
| **Client/** | Client behavioral logic (subfolders at 5+ files) | `*ClientStateMachine`, `FlowController`, `*ClientEncoder`, `*ClientDecoder` |
| **Server/** | Server behavioral logic (subfolders at 5+ files) | `*ServerStateMachine`, `*ServerEncoder`, `*ServerDecoder` |
| **Hpack/** / **Qpack/** | Header compression (own RFC) | `HpackEncoder`/`QpackEncoder`, dynamic/static tables |
| **Security/** | Fuzz, adversarial, resource exhaustion | Any, from attacker perspective |
| **Stages/** | Akka Streams integration (GraphDsl) | `*ConnectionStage` |
| **Options/** | Configuration validation stubs | `*Options` types |

**Decision rule**: `FrameDecoder` + frame assertions → Frames/. `*StateMachine`/`*Encoder`/`*Decoder` → Client/ or Server/. Akka Streams graph → Stages/.

Http10/Http11 use flat `Client/` and `Server/` (no subfolders).

## Stage Port Naming (Quick Reference)

Ports follow `StageName.Direction` or `StageName.Direction.Role` (PascalCase). Drop `Stage` suffix, no protocol prefix, globally unique names.
Expand All @@ -114,26 +142,14 @@ Prefer retrieval-led reasoning over pretraining for any .NET work.

## Sequential Thinking MCP (`mcp__sequential-thinking__sequentialthinking`)

Use for multi-step reasoning where the full scope isn't clear upfront. The tool lets you think
step-by-step with the ability to revise, branch, and extend as understanding deepens.
Use for multi-step reasoning where the full scope isn't clear upfront.

**When to use:**

- Complex debugging where the root cause isn't obvious
- Architecture/design decisions with multiple trade-offs
- RFC compliance analysis requiring cross-referencing multiple sections
- Any problem where early assumptions may need revision

**How it works:** Call the tool repeatedly, once per thought step. Each call takes:

- `thought` — your current reasoning step (analysis, revision, hypothesis, verification)
- `thoughtNumber` / `totalThoughts` — track position; adjust `totalThoughts` up/down as needed
- `nextThoughtNeeded` — `true` to continue, `false` when done
- `isRevision` + `revisesThought` — mark a step as reconsidering an earlier thought
- `branchFromThought` + `branchId` — explore an alternative path without losing the main line

**Pattern:** Analyze → Hypothesize → Verify → Conclude. Revise or branch whenever new
information contradicts earlier steps. Don't force linear progression — backtrack freely.
Call repeatedly, one thought per step. Revise or branch freely when new information contradicts earlier steps.

## Roslyn Navigator — Required Before Commit

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 st0o0
Copyright (c) 2026 leberkas-org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
76 changes: 59 additions & 17 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from 'vitepress'

export default defineConfig({
title: 'TurboHTTP',
description: 'High-performance HTTP client library for .NET built on Akka.Streams — HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3 (QUIC) with automatic retries, caching, cookies, and connection pooling.',
description: 'High-performance HTTP client and server for .NET built on Akka.Streams — HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3 (QUIC) with automatic retries, caching, cookies, connection pooling, middleware pipeline, routing, and entity gateway.',
base: '/',
head: [
['link', { rel: 'icon', type: 'image/png', href: '/logo/icon.png' }],
Expand All @@ -15,40 +15,82 @@ export default defineConfig({

nav: [
{ text: 'Home', link: '/' },
{ text: 'Guide', link: '/guide/' },
{ text: 'Quick Guide', link: '/quickstart/' },
{ text: 'Client', link: '/client/' },
{ text: 'Server', link: '/server/' },
{ text: 'Architecture', link: '/architecture/' },
{ text: 'API', link: '/api/' },
{ text: 'Why TurboHTTP?', link: '/why/' },
],

sidebar: {
'/guide/': [
'/quickstart/': [
{
text: 'Quick Guide',
items: [
{ text: 'Quick Guide', link: '/quickstart/' },
],
},
],
'/client/': [
{
text: 'Getting Started',
items: [
{ text: 'Quick Start', link: '/guide/' },
{ text: 'Installation & Setup', link: '/guide/installation' },
{ text: 'Configuration', link: '/guide/configuration' },
{ text: 'Migration from HttpClient', link: '/guide/migration' },
{ text: 'Quick Start', link: '/client/' },
{ text: 'Installation & Setup', link: '/client/installation' },
{ text: 'Configuration', link: '/client/configuration' },
{ text: 'Migration from HttpClient', link: '/client/migration' },
],
},
{
text: 'Features',
items: [
{ text: 'Automatic Retries', link: '/guide/retries' },
{ text: 'HTTP Caching', link: '/guide/caching' },
{ text: 'Cookie Management', link: '/guide/cookies' },
{ text: 'Redirects', link: '/guide/redirects' },
{ text: 'Content Encoding', link: '/guide/content-encoding' },
{ text: 'Connection Pooling', link: '/guide/connection-pooling' },
{ text: 'HTTP/2 & Multiplexing', link: '/guide/http2' },
{ text: 'HTTP/3 & QUIC', link: '/guide/http3' },
{ text: 'Automatic Retries', link: '/client/retries' },
{ text: 'HTTP Caching', link: '/client/caching' },
{ text: 'Cookie Management', link: '/client/cookies' },
{ text: 'Redirects', link: '/client/redirects' },
{ text: 'Content Encoding', link: '/client/content-encoding' },
{ text: 'Connection Pooling', link: '/client/connection-pooling' },
{ text: 'HTTP/2 & Multiplexing', link: '/client/http2' },
{ text: 'HTTP/3 & QUIC', link: '/client/http3' },
],
},
{
text: 'Help',
items: [
{ text: 'Troubleshooting & FAQ', link: '/client/troubleshooting' },
],
},
],
'/server/': [
{
text: 'Getting Started',
items: [
{ text: 'Quick Start', link: '/server/' },
{ text: 'Installation & Setup', link: '/server/installation' },
{ text: 'Configuration', link: '/server/configuration' },
{ text: 'Hosting & Lifecycle', link: '/server/hosting' },
],
},
{
text: 'Features',
items: [
{ text: 'Middleware Pipeline', link: '/server/middleware' },
{ text: 'Routing', link: '/server/routing' },
{ text: 'Entity Gateway', link: '/server/entity-gateway' },
],
},
{
text: 'Advanced',
items: [
{ text: 'Parameter Binding', link: '/server/binding' },
{ text: 'Validation', link: '/server/validation' },
],
},
{
text: 'Help',
items: [
{ text: 'Troubleshooting & FAQ', link: '/guide/troubleshooting' },
{ text: 'Troubleshooting', link: '/server/troubleshooting' },
],
},
],
Expand Down Expand Up @@ -85,7 +127,7 @@ export default defineConfig({
},

socialLinks: [
{ icon: 'github', link: 'https://github.com/st0o0/TurboHTTP' },
{ icon: 'github', link: 'https://github.com/leberkas-org/TurboHTTP' },
],

footer: {
Expand Down
Loading
Loading