Skip to content

Parse extension headers with HTTP whitespace and full boundaries - #9

Open
OskarEichler wants to merge 4 commits into
faye:mainfrom
OskarEichler:codex/header-whitespace-and-boundaries
Open

Parse extension headers with HTTP whitespace and full boundaries#9
OskarEichler wants to merge 4 commits into
faye:mainfrom
OskarEichler:codex/header-whitespace-and-boundaries

Conversation

@OskarEichler

Copy link
Copy Markdown

Summary

Accept space/tab HTTP whitespace around delimiters and require complete header/value matches. Avoid returning a partial parse from a matching line within a larger string.

Reproduction and verification

p = WebSocket::Extensions::Parser
p p.parse_header(" \text \t; mode \t= compress \t, other \t").to_a
# two offers, ext with mode=compress and other without parameters

261 focused whitespace/boundary cases pass. RFC 6455 section 9.1 uses the implied HTTP whitespace rule: https://www.rfc-editor.org/rfc/rfc6455.html#section-9.1 . Transport-level folded header lines must be unfolded before parsing. Existing broader quoted-string acceptance is deliberately unchanged. Paired small-header measurements show about 0.12 microseconds additional parsing cost (1.804 to 1.926 microseconds); this is handshake parsing, not a message-throughput speedup claim.

  • Ruby 4.0.6 through rbenv; existing current-upstream suite: 64 examples, zero failures on this isolated change.
  • The cumulative release-based candidate passes 283 focused checks (272 baseline failures → zero), 2,784 model checks, the current upstream's 64-example suite, and gem build/extraction.
  • The historical 0.1.5 suite has three Ruby keyword-versus-options-hash mock failures on both baseline and candidate. Current upstream already corrected those expectations; they were run against the candidate through an external preload without changing repository tests.
  • No new or modified tests/specs, following the consumer repository's explicit policy. Reproductions/models were run from external scratch scripts.

Breaking changes and limitations

Intentional correction: invalid unquoted newline suffixes/prefixes now raise ParseError instead of producing partial/empty results; supported space/tab formatting is accepted. Numeric coercion checks the entire decoded value.

Only local Ruby 4.0.6/macOS execution is claimed; the repository's older Ruby/JRuby matrix needs upstream CI. No production access or unrelated release upgrades.

@jcoglan

jcoglan commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Just leaving a note for myself on this one that the full "implied *LWS" rule in RFC 2616 actually says that words may be separated by *LWS where LWS is defined as [CRLF] 1*( SP | HT ).

As a regex, this would be ((\r\n)?( |\t)+)*. As written, that pattern is a ReDoS vector and we have had problems with this in the past. Whereas, we have not had any complaints about the parser's behaviour on real-world headers.

So, we would need a compelling reason to implement this which requires additional effort to find a non-ReDoS way of expressing the "implied *LWS" syntax.

@jcoglan

jcoglan commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Further note: a non-ReDoS pattern for implied *LWS is: [ \t]*(\r\n[ \t]+)*

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.

2 participants