Open KingMob opened 1 year ago
Update: based on a conversation on an h2spec issue, there's some ambiguity on whether just sending an HTTP response and closing the stream is also acceptable.
I've asked the RFC 9113 authors for clarification. Even if that's true, and h2spec has a bug, I didn't see that as the rationale in why the tests are excluded. If so, that decision should be documented.
Even if a response+end-of-stream turns out to be acceptable for stream errors, I would still suggest Netty handle it, to prevent putting the burden of missing pseudo-headers on implementers.
Regardless, it doesn't fix the subproblem of the out-of-date h2spec plugin reporting differently from h2spec.
The HTTP working group weighed in at https://lists.w3.org/Archives/Public/ietf-http-wg/2023JulSep/0183.html
They think a response+close is a defensible interpretation, if not ideal, and instead recommend a 4xx response+RST_STREAM.
Expected behavior
A minimal Netty HTTP/2 server should follow RFC 9113, and pass h2spec compliance (barring reasonable disagreement over any ambiguity). In particular, it should pass the 8.1.2.3 specs, which specify that if required pseudo-headers are missing, it should be a failure.
Relevant RFC sections
From RFC 9113 § 8.1.1:
From RFC 9113 § 8.3.1-8.3.2:
and
Actual behavior
Netty fails to check for the presence of mandatory pseudo-headers.
NB: Netty correctly checks the pseudo-headers' values if present, but not the presence/absence of the pseudo-headers themselves.
Steps to reproduce
cd testsuite-http2
mvn test
h2spec will run, and list, the failures in the console output, but because they're excluded in the pom.xml, the test "succeeds".
h2spec console output:
(Theoretically, RFC 9113 § 8.1.1 means HEADERS/DATA frames can be sent after getting a malformed frame. However, that's only allowed prior to sending a GOAWAY or RST_STREAM: "For malformed requests, a server MAY send an HTTP response prior to closing or resetting the stream." h2spec reports the final frame it received before it timed out or the conn closed, which means no RST_STREAM or GOAWAY was ever sent.)
mvn test
Now we see
mvn test
failing, but we also see a second subproblem: the h2spec-maven-plugin doesn't report what h2spec itself does:The h2spec-maven-plugin claims the final frame was a RST_STREAM, while h2spec itself earlier claimed it was a DATA frame. I think this is a separate bug, which masks the underlying issue by making it look like netty is actually detecting the error and just disagreeing over what error frame to send, but that's not correct. Netty's version of h2spec-maven-plugin is a bit old. If we switch to a newer fork, the
org.mortbay.jetty
h2spec-maven-plugin
, version1.0.10
, the h2spec-maven-plugin and h2spec agree on what the final frame is: a DATA frame.Manual check
I also double-checked this behavior by hand on the example multiplex "Hello World" server, and ran h2spec against it in verbose mode, which lists the frames received. h2spec never gets a single RST_STREAM or GOAWAY frame from the server, just a sequence of normal frames:
Minimal yet complete reproducer code (or URL to code)
n/a
Netty version
4.1.98.Final and main branch SHA 391e019cd4fee699d8812d6837689601cb3daecd
JVM version (e.g.
java -version
)openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment Temurin-17.0.8+7 (build 17.0.8+7) OpenJDK 64-Bit Server VM Temurin-17.0.8+7 (build 17.0.8+7, mixed mode, sharing)
OS version (e.g.
uname -a
)Darwin Lappy.local 22.6.0 Darwin Kernel Version 22.6.0: Wed Jul 5 22:21:56 PDT 2023; root:xnu-8796.141.3~6/RELEASE_X86_64 x86_64