Skip to content

chore(engines): Update Glyph11 to 0.4.0 and drop Glyph11.Pico - #973

Merged
Kaliumhexacyanoferrat merged 4 commits into
mainfrom
update-glyph11-0.4.0
Nov 4, 2026
Merged

Kaliumhexacyanoferrat merged 4 commits into
mainfrom
update-glyph11-0.4.0

Conversation

@MDA2AV

@MDA2AV MDA2AV commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #972

Glyph11 0.4.0 marks the parse entry points both engines use [Obsolete] (dotnet-web-stack/Glyph11#81): TryExtractFullHeaderValidated and TryExtractFullHeaderROM report one less than the length of the header block. With TreatWarningsAsErrors that breaks the build. TryParseRequestHeader reports the length itself, so the body starts at consumed.

  • Migration (first commit): both engines, the body lifecycle tests and the benchmark context call TryParseRequestHeader and slice at consumed, dropping the + 1 in the same change. Glyph11 goes to 0.4.0 in Engine.Shared, Engine.Internal and Engine.Ioxide.
  • Version handling (second commit, for Reject malformed HTTP versions with 400, unsupported ones with 505 dotnet-web-stack/Glyph11#79): 0.4.0 answers a malformed version with 400 and keeps 505 for a well-formed version it doesn't support.
    • ComplianceTests.TestNoMinorHttpVersion sends HTTP/1 and now expects 400, which is also what http-probe's COMP-VERSION-MISSING-MINOR expects.
    • WireTests.TestUnsupportedProtocolVersion sends HTTP/2.0, which is still a 505, and now matches the new message.
  • Streamed chunk data (third commit, for Bound chunked decoding: stream chunk data, cap the trailer section dotnet-web-stack/Glyph11#83): ChunkedBodyStream hands data out as it arrives. TestTruncatedBodyFails sends 5\r\nHel: the first read now returns the three bytes that arrived, and the second read gets the 400. ChunkedFraming itself needed no change.
  • No Glyph11.Pico (fourth commit): Glyph11 discontinues Glyph11.Pico and Glyph11.Native (Drop the bindings and the C core: Glyph11 is managed-only dotnet-web-stack/Glyph11#84), and 0.4.0 no longer exposes its internals to Pico, so the package has to go in the same change.
    • The Ioxide engine loses its GENHTTP_IOXIDE_PARSER=pico benchmarking switch and always parses with UltraHardenedParser.
    • The body lifecycle tests that need unvalidated framing headers now get them from Glyph11's FlexibleParser.

Both of those Glyph11 PRs shipped in 0.4.0, so both commits are needed.

Verification

Glyph11 0.4.0 is now on NuGet, so CI can restore it. It ships dotnet-web-stack/Glyph11#74 through dotnet-web-stack/Glyph11#89. I tested locally against the published package, restored from nuget.org only:

  • dotnet build GenHTTP.slnx -c Release finishes with 0 warnings under TreatWarningsAsErrors, so no obsolete call is left, and Glyph11.Pico is no longer in the dependency graph.
  • Acceptance suite, after all four commits: 2,879 passed, 0 failed, 4 skipped on net11.0 and 2,876 passed, 0 failed, 4 skipped on net10.0.
  • Before the second and third commits, a net11.0 run against a pre-release build of 0.4.0 failed exactly the five cases those commits adapt: TestNoMinorHttpVersion three times and the two tests named above.

Noticed on the way, not changed here: WireTest.TestAsync(string[] request, ..., ServerEngine engine) doesn't pass engine on to the overload it calls, so every [MultiEngineTest] case in ComplianceTests runs on the internal engine. I tried forwarding it locally:

  • TestNoMinorHttpVersion gets 400 on all three engines, Kestrel included.
  • TestPostNoBody gets 400 instead of 404 on Kestrel.
  • TestChunkWithSemicolon gets 500 instead of 400 on Kestrel.

The last two have nothing to do with this change, so I left the helper alone.

Glyph11 0.4.0 marks TryExtractFullHeaderValidated and TryExtractFullHeaderROM
[Obsolete]: they report one less than the length of the header block, which
is why every call site here sliced at bytesRead + 1. TryParseRequestHeader
reports the length itself, so the body starts at consumed.

With TreatWarningsAsErrors the update does not build without the move, and the
rename and the dropped + 1 have to land together - renaming alone would skip
the first byte of every body or pipelined request. Both engines, the body
lifecycle tests and the benchmark context move. Glyph11.Pico stays at 0.0.1:
PicoParser.TryParse keeps its convention, so the Pico path keeps its + 1.

Closes #972.
Glyph11 0.4.0 (dotnet-web-stack/Glyph11#79) splits what it used to report
as one 505: a version that matches HTTP-version ("HTTP/" DIGIT "." DIGIT)
but is not 1.0/1.1 stays a 505, "Unsupported HTTP version.", while bytes
that are not an HTTP-version at all make the request line invalid, a 400
(RFC 9112 2.3 and 3).

"GET / HTTP/1" has no minor version, so it is malformed rather than
unsupported, which is also what http-probe's COMP-VERSION-MISSING-MINOR
expects. HTTP/2.0 keeps its 505, under the new message.
Glyph11 0.4.0 (dotnet-web-stack/Glyph11#83) hands chunk data out as it
arrives instead of waiting for the whole chunk, so a peer that declares a
huge chunk can no longer make the connection buffer it. For "5\r\nHel" the
first read now returns the three bytes that did arrive, and the truncation
surfaces as the 400 ProviderException on the next read - the point where
the body actually ends early.
Glyph11 discontinues Glyph11.Pico and Glyph11.Native
(dotnet-web-stack/Glyph11#84): they get no further releases. The Ioxide
engine's GENHTTP_IOXIDE_PARSER=pico switch goes with the package, so
requests are always parsed by UltraHardenedParser, and the body
lifecycle tests that need unvalidated framing headers get them from
Glyph11's FlexibleParser instead of picohttpparser.
MDA2AV added a commit to dotnet-web-stack/Glyph11 that referenced this pull request Nov 2, 2026
The friend access was kept so that the published Glyph11.Pico 0.0.1
could keep running next to newer Glyph11 releases, as GenHTTP shipped
it. GenHTTP drops Glyph11.Pico in the same upgrade to 0.4.0
(Kaliumhexacyanoferrat/GenHTTP#973), so nothing needs it any more.
Glyph11.Pico 0.0.1 now fails with MethodAccessException next to Glyph11
0.4.0 or later; it keeps working with 0.3.x.
@MDA2AV MDA2AV changed the title chore(engines): Update Glyph11 to 0.4.0 and move off its obsolete parse API chore(engines): Update Glyph11 to 0.4.0 and drop Glyph11.Pico Nov 2, 2026
MDA2AV added a commit to dotnet-web-stack/Glyph11 that referenced this pull request Nov 3, 2026
* Remove the bindings and the C core

Glyph11 is managed-only from here on: the bindings are no longer
supported, so carrying them means maintaining a second and third
implementation of every rule (and a Gradle toolchain) for packages that
will not be released again.

Removed: bindings/ (Kotlin, Glyph11.Native, Glyph11.Pico with the
vendored picohttpparser), core/ (the C parser, its tests and the C-vs-C#
differential harness), the two native example projects, and the
core-tests / package-native / package-pico workflows. release.yml now
publishes only Glyph11, and the solution drops the four binding projects.
The benchmark keeps the Glyph11 measurements and loses the native
columns and decoder.

InternalsVisibleTo("Glyph11.Pico") stays in Glyph11.csproj. The published
Glyph11.Pico 0.0.1 sets BinaryRequest's internal setters and calls
KeyValueList.Add, and the runtime enforces friend access, so dropping the
attribute would make Pico fail with MethodAccessException against the
next Glyph11 release - GenHTTP still ships it next to Glyph11.

Closes #57, closes #66, closes #69, closes #70, closes #72.

* Docs: Glyph11 is one managed package

With the bindings gone, the README, the docs site, the examples index and
the benchmark README described three packages and their native build
steps. They now describe the managed parser only: the three-package
table, the "all three produce the same data" claim, the Native / Pico /
Kotlin sections and the native build instructions are removed; the
benchmark tables keep the existing Glyph11 numbers; the site loses the
Native and Pico pages from its navigation. A short note says that
Glyph11.Native and Glyph11.Pico are discontinued: their published
versions stay on NuGet but get no further releases.

Also fixes the harness link, which pointed at a bench/ directory that
does not exist (the harness lives in Benchmarks/).

Refs #57, #66, #69, #70, #72.

* Stop exposing internals to Glyph11.Pico

The friend access was kept so that the published Glyph11.Pico 0.0.1
could keep running next to newer Glyph11 releases, as GenHTTP shipped
it. GenHTTP drops Glyph11.Pico in the same upgrade to 0.4.0
(Kaliumhexacyanoferrat/GenHTTP#973), so nothing needs it any more.
Glyph11.Pico 0.0.1 now fails with MethodAccessException next to Glyph11
0.4.0 or later; it keeps working with 0.3.x.
@MDA2AV
MDA2AV marked this pull request as ready for review November 3, 2026 20:36
@Kaliumhexacyanoferrat
Kaliumhexacyanoferrat merged commit 690c7d3 into main Nov 4, 2026
10 of 11 checks passed
@Kaliumhexacyanoferrat
Kaliumhexacyanoferrat deleted the update-glyph11-0.4.0 branch November 4, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Glyph11 0.4.0: the engines' parse API is obsolete, and Glyph11.Pico is discontinued

2 participants