diff --git a/Benchmarks/Infrastructure/BenchmarkContext.cs b/Benchmarks/Infrastructure/BenchmarkContext.cs
index 1651292c..3dc8c105 100644
--- a/Benchmarks/Infrastructure/BenchmarkContext.cs
+++ b/Benchmarks/Infrastructure/BenchmarkContext.cs
@@ -29,7 +29,7 @@ public BenchmarkContext(string request, IHandler handler)
public async ValueTask Execute()
{
- if (!UltraHardenedParser.TryExtractFullHeaderROM(ref _request, _context.Request.Source, Limits, out _))
+ if (!UltraHardenedParser.TryParseRequestHeader(ref _request, _context.Request.Source, Limits, out _))
{
throw new ArgumentException("Given request could not be parsed.");
}
diff --git a/Engine/Internal/GenHTTP.Engine.Internal.csproj b/Engine/Internal/GenHTTP.Engine.Internal.csproj
index 25609076..ab2376d4 100644
--- a/Engine/Internal/GenHTTP.Engine.Internal.csproj
+++ b/Engine/Internal/GenHTTP.Engine.Internal.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/Engine/Internal/Protocol/ClientHandler.cs b/Engine/Internal/Protocol/ClientHandler.cs
index 65e02b64..baa5b7f9 100644
--- a/Engine/Internal/Protocol/ClientHandler.cs
+++ b/Engine/Internal/Protocol/ClientHandler.cs
@@ -185,12 +185,12 @@ private async ValueTask HandlePipeAsync(PipeReader reader)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryParseRequest(ref ReadOnlySequence buffer, BinaryRequest into)
{
- if (!UltraHardenedParser.TryExtractFullHeaderValidated(ref buffer, into, Limits, out var bytesRead))
+ if (!UltraHardenedParser.TryParseRequestHeader(ref buffer, into, Limits, out var consumed))
{
return false;
}
- buffer = buffer.Slice(bytesRead + 1);
+ buffer = buffer.Slice(consumed);
return true;
}
diff --git a/Engine/Ioxide/GenHTTP.Engine.Ioxide.csproj b/Engine/Ioxide/GenHTTP.Engine.Ioxide.csproj
index 1f848c8e..df36c082 100644
--- a/Engine/Ioxide/GenHTTP.Engine.Ioxide.csproj
+++ b/Engine/Ioxide/GenHTTP.Engine.Ioxide.csproj
@@ -22,8 +22,7 @@
-
-
+
diff --git a/Engine/Ioxide/Protocol/Drivers/Tcp/Http1Driver.cs b/Engine/Ioxide/Protocol/Drivers/Tcp/Http1Driver.cs
index 87b5597f..065cc6fc 100644
--- a/Engine/Ioxide/Protocol/Drivers/Tcp/Http1Driver.cs
+++ b/Engine/Ioxide/Protocol/Drivers/Tcp/Http1Driver.cs
@@ -10,7 +10,6 @@
using Glyph11;
using Glyph11.Parser;
using Glyph11.Parser.UltraHardened;
-using Glyph11.Pico;
using Glyph11.Protocol;
using Microsoft.Extensions.Logging;
@@ -28,11 +27,6 @@ internal static class Http1Driver
{
private static readonly ParserLimits Limits = ParserLimits.Default;
- // GENHTTP_IOXIDE_PARSER=pico swaps the hardened managed parser for picohttpparser, which
- // does no path/token/smuggling hardening. For benchmarking, not for untrusted traffic.
- private static readonly bool UsePico =
- string.Equals(Environment.GetEnvironmentVariable("GENHTTP_IOXIDE_PARSER"), "pico", StringComparison.OrdinalIgnoreCase);
-
private static readonly ByteString KeepAliveValue = new("Keep-Alive");
[ThreadStatic]
@@ -147,31 +141,15 @@ private static async ValueTask SendErrorAsync(IServer server, PipeWriter writer,
}
}
- // Parses one request head, through whichever parser this process was started with.
+ // Parses one request head: full RFC validation plus smuggling hardening.
private static bool TryParseRequest(ref ReadOnlySequence buffer, BinaryRequest into)
- => UsePico ? TryParseRequestPico(ref buffer, into) : TryParseRequestGlyph11(ref buffer, into);
-
- // The default path: full RFC validation plus smuggling hardening.
- private static bool TryParseRequestGlyph11(ref ReadOnlySequence buffer, BinaryRequest into)
- {
- if (!UltraHardenedParser.TryExtractFullHeaderValidated(ref buffer, into, Limits, out var bytesRead))
- {
- return false;
- }
-
- buffer = buffer.Slice(bytesRead + 1);
- return true;
- }
-
- // The benchmark path: picohttpparser, which validates only as far as picohttpparser does.
- private static bool TryParseRequestPico(ref ReadOnlySequence buffer, BinaryRequest into)
{
- if (!PicoParser.TryParse(buffer, into, out var consumed))
+ if (!UltraHardenedParser.TryParseRequestHeader(ref buffer, into, Limits, out var consumed))
{
return false;
}
- buffer = buffer.Slice(consumed + 1);
+ buffer = buffer.Slice(consumed);
return true;
}
diff --git a/Engine/Shared/GenHTTP.Engine.Shared.csproj b/Engine/Shared/GenHTTP.Engine.Shared.csproj
index ccdbba89..e4afd6cc 100644
--- a/Engine/Shared/GenHTTP.Engine.Shared.csproj
+++ b/Engine/Shared/GenHTTP.Engine.Shared.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/Testing/Acceptance/Engine/Body/ChunkedFramingTests.cs b/Testing/Acceptance/Engine/Body/ChunkedFramingTests.cs
index b1542ada..78584a33 100644
--- a/Testing/Acceptance/Engine/Body/ChunkedFramingTests.cs
+++ b/Testing/Acceptance/Engine/Body/ChunkedFramingTests.cs
@@ -194,7 +194,12 @@ public async Task TestTruncatedBodyFails()
{
var (_, framing) = await CreateAsync("5\r\nHel");
- var e = await Assert.ThrowsExactlyAsync(async () => await framing.ReadAsync(new byte[16], CancellationToken.None));
+ var buffer = new byte[16];
+
+ Assert.AreEqual(3, await framing.ReadAsync(buffer, CancellationToken.None));
+ Assert.AreEqual("Hel", Encoding.ASCII.GetString(buffer, 0, 3));
+
+ var e = await Assert.ThrowsExactlyAsync(async () => await framing.ReadAsync(buffer, CancellationToken.None));
Assert.AreEqual(ResponseStatus.BadRequest, e.Status);
}
diff --git a/Testing/Acceptance/Engine/Body/RequestBodyLifecycleTests.cs b/Testing/Acceptance/Engine/Body/RequestBodyLifecycleTests.cs
index cfc38f8b..26d4efcd 100644
--- a/Testing/Acceptance/Engine/Body/RequestBodyLifecycleTests.cs
+++ b/Testing/Acceptance/Engine/Body/RequestBodyLifecycleTests.cs
@@ -9,8 +9,8 @@
using GenHTTP.Engine.Shared.Types;
using Glyph11.Parser;
+using Glyph11.Parser.FlexibleParser;
using Glyph11.Parser.UltraHardened;
-using Glyph11.Pico;
using NSubstitute;
@@ -453,9 +453,9 @@ public async Task TestContinueNotCarriedOver()
var buffer = (await pipe.Reader.ReadAsync()).Buffer;
- Assert.IsTrue(UltraHardenedParser.TryExtractFullHeaderValidated(ref buffer, request.Source, ParserLimits.Default, out var bytesRead));
+ Assert.IsTrue(UltraHardenedParser.TryParseRequestHeader(ref buffer, request.Source, ParserLimits.Default, out var consumed));
- request.Apply(Substitute.For(), Substitute.For(), pipe.Reader, buffer.Slice(bytesRead + 1).Start, null, null, output.Writer);
+ request.Apply(Substitute.For(), Substitute.For(), pipe.Reader, buffer.Slice(consumed).Start, null, null, output.Writer);
await request.GetBody()!.AsMemoryAsync();
@@ -520,14 +520,14 @@ public async Task TestWithoutConnection()
if (validate)
{
- Assert.IsTrue(UltraHardenedParser.TryExtractFullHeaderValidated(ref buffer, request.Source, ParserLimits.Default, out var bytesRead));
- buffer = buffer.Slice(bytesRead + 1);
+ Assert.IsTrue(UltraHardenedParser.TryParseRequestHeader(ref buffer, request.Source, ParserLimits.Default, out var consumed));
+ buffer = buffer.Slice(consumed);
}
else
{
- // picohttpparser does not validate the framing headers, so they reach the request as sent
- Assert.IsTrue(PicoParser.TryParse(buffer, request.Source, out var consumed));
- buffer = buffer.Slice(consumed + 1);
+ // FlexibleParser does not validate the framing headers, so they reach the request as sent
+ Assert.IsTrue(FlexibleParser.TryParseRequestHeader(ref buffer, request.Source, out var consumed));
+ buffer = buffer.Slice(consumed);
}
var endPoint = Substitute.For();
diff --git a/Testing/Acceptance/Engine/Compliance/ComplianceTests.cs b/Testing/Acceptance/Engine/Compliance/ComplianceTests.cs
index d811e26d..a62610a2 100644
--- a/Testing/Acceptance/Engine/Compliance/ComplianceTests.cs
+++ b/Testing/Acceptance/Engine/Compliance/ComplianceTests.cs
@@ -12,7 +12,7 @@ public class ComplianceTests : WireTest
[MultiEngineTest]
public async Task TestNoMinorHttpVersion(ServerEngine engine)
{
- await TestAsync(["GET / HTTP/1", "Host: localhost"], "505", Layout.Create(), engine);
+ await TestAsync(["GET / HTTP/1", "Host: localhost"], "400", Layout.Create(), engine);
}
[TestMethod]
diff --git a/Testing/Acceptance/Engine/WireTests.cs b/Testing/Acceptance/Engine/WireTests.cs
index ae8d29b4..042dd0d2 100644
--- a/Testing/Acceptance/Engine/WireTests.cs
+++ b/Testing/Acceptance/Engine/WireTests.cs
@@ -18,7 +18,7 @@ public async Task TestNoHost()
[TestMethod]
public async Task TestUnsupportedProtocolVersion()
{
- await TestAsync("GET / HTTP/2.0\r\n", "Invalid HTTP version");
+ await TestAsync("GET / HTTP/2.0\r\n", "Unsupported HTTP version");
}
[TestMethod]