client: validate streaming gRPC response content types - #266
Conversation
Signed-off-by: EffortlessSteven <git@effortlesssteven.com>
…status Share the unary path's HTTP-status / content-type gate with make_server_stream as check_grpc_response_head, and run it before the trailers-only check. A trailers-only reply in the wrong content-type family is now rejected on both paths instead of being believed for its grpc-status on the streaming one, and a non-2xx reply that is not speaking gRPC carries the same content-type detail after its HTTP status. Adds a parity test driving the same response head through both parsers across the status / content-type / grpc-status matrix, two accept-side rows (grpc+json exact match; Connect streaming unaffected), and corrects a test comment about connect-go's bare-type rule. Signed-off-by: Iain McGinniss <309153+iainmcgin@users.noreply.github.com>
c8aec5c to
9b9fbcb
Compare
|
[claude code] Thanks for this — the fix is well-placed and the tests are thorough. To get it into 0.9.0 I've rebased the branch onto current The fixup addresses one behavioural question the review turned up. With the validation placed after the trailers-only check, a trailers-only reply carrying a wrong-family content-type and a non-zero Also in the fixup: a parity test that drives the same response head through both parsers across the status / content-type / grpc-status matrix; two extra accept-side rows ( Verified locally on the rebased branch: 635 unit tests, client conformance gRPC 1454/0 and gRPC-Web 2838/0. Connect-protocol streaming responses remain unvalidated here (connect-go does check them); the failure mode is a clean |
…alse codegen collision procedure_uri's no-prefix fast path used PathAndQuery::from_static, which panics on a byte that is illegal in a path (a space, #, non-ASCII) while the prefixed path returned internal for the same Spec; both now validate through from_maybe_shared over Bytes::from_static, still without allocating. check_method_collisions rejected Get + GetSpec as a clash on get_spec, but the constants are X_GET_SPEC and X_GET_SPEC_SPEC and get_spec is only a client method name, so the pair compiles again and the test pins that. Spec's type doc said it could be "compared freely"; it now says PartialEq and Hash include origin, which is why a client-side value is not == the generated constant, and points at same_method, which takes its argument by value since Spec is Copy. Spec::client and Spec::server gain # Panics sections. The per-constant doc codegen emits is cut to one sentence so a forty-method service does not carry forty copies of a paragraph about Spec. ClientConfig::new documents how request URIs are formed from the base, and the changelog snippet gains its imports. The conformance client used the generated constant regardless of the service and method the suite named; client_spec() keeps the constant when they match and builds an ad-hoc client Spec otherwise. One connectrpc#266 test moves to the Spec-based call signature. Signed-off-by: Iain McGinniss <309153+iainmcgin@users.noreply.github.com> (cherry picked from commit 948178da98a2af553d55b7c9055dcb5b3a484ea1)
What this does
Server-streaming and bidi receive initialization did not validate that a successful response's
content-typematched the configured gRPC family or codec. In the trailers-only regression, a gRPC client acceptedapplication/grpc-web+proto:call_server_streamreturnedOk(ServerStream), thenmessage()returnedOk(None).make_server_streamnow reuses the unary validator after response-status classification and before encoding or stream construction. Missing and bare-family content types remain accepted; Connect and non-200 HTTP precedence are unchanged.Fixes #203.
Verification
Ok(ServerStream)thenOk(None); patchedUnknownbefore stream exposuregrpc-status; headers and compatibility cases preservedReview map
validate_grpc_response_content_type: takes protocol and codec directly.make_server_stream: shared server-streaming and bidi validation seam.