Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ErrorWriter.IsSupported is overly strict #689

Closed
jhump opened this issue Feb 16, 2024 · 0 comments · Fixed by #701
Closed

ErrorWriter.IsSupported is overly strict #689

jhump opened this issue Feb 16, 2024 · 0 comments · Fixed by #701
Labels
bug Something isn't working

Comments

@jhump
Copy link
Member

jhump commented Feb 16, 2024

Currently ErrorWriter.IsSupported uses the currently supported codecs (provided in the form of handler options) to compute all of the possible content-types that the server would support. However, this is not necessary. There are only four protocol types, and the actual registered codecs aren't necessary in order to classify them:

  1. If the content-type is application/grpc or starts with application/grpc+ then it's a gRPC request.
  2. If the content-type is application/grpc-web or starts with application/grpc-web+ then it's a gRPC-Web request.
  3. If the content-type starts with application/connect+ then it's a Connect streaming request.
  4. Lastly, if the content-type starts with application/ and matches none of the above OR it has a Connect-Protocol-Version: 1 header OR it uses a GET HTTP method and includes a connect=v1 query param then it's a Connect unary request.
  5. Only when none of the above apply should the request be un-classifiable and IsSupported return false.

In all of the above cases, the actual supported codecs are irrelevant because, once classified as above, an error can be correctly written (error formats are codec-agnostic).

Addressing this would also enable error handling that more closely resembles gRPC. In gRPC servers, if the content-type is not a gRPC content-type (i.e. it is not application/grpc and does not start with application/grpc+) then the server sends back a 415 HTTP status code, which clients will then classify as an unknown error. If it's a gRPC content-type, but not a supported codec, the server sends back a gRPC error (HTTP status code 200, error code and message in HTTP trailers) with a code of "internal". So with the above logic, when the content-type is not supported, an ErrorWriter could be used to write an RPC internal error and a 415 HTTP status code only used if the ErrorWriter reports that the request is unsupported.

@jhump jhump added the bug Something isn't working label Feb 16, 2024
jhump added a commit that referenced this issue Feb 16, 2024
This largely undoes a recent change to do more validation of
trailers-only responses (#685), which disallows a body or trailers in
what appeared to be a trailers-only response. In that change, a
trailers-only response was identified by the presence of a "grpc-status"
key in the headers.

In this PR, a trailers-only response is instead defined by the lack of
body and trailers (not the presence of a "grpc-status" header). This PR
also tweaks some other error scenarios:

* If trailers (or an end-stream message) is completely missing from a
response, it's considered an `internal` error. But if trailers are
present, but the "grpc-status" key is missing, it's considered an issue
determining the status, which is an `unknown` error.
* Similarly, if a response content-type doesn't appear to be the right
protocol (like it may have come from a non-RPC server), the error code
is now `unknown`. But if it looks like the right protocol but uses the
wrong sub-format/codec, it's an `internal` error.
* Note that in grpc-go, this behavior is also seen in the client, but
this PR doesn't attempt to address that in the connect-go client.
Instead, that change can be made when #689 is addressed.

This PR also now makes connect-go more strict about the "compressed"
flag in a streaming protocol when there was no compression algorithm
negotiated. Previously, this library was lenient and did not consider it
an error if the message in question was empty (zero bytes). But to
correctly adhere to gRPC semantics, it must report this case as an
`internal `error.
emcfarlane added a commit that referenced this issue Mar 12, 2024
This PR changes the ErrorWriter to be more lenient with classifying
protocols. Errors codecs are agnostic to the codec used. Therefore we
avoid checking the codec in classifying the request. IsSupported will
return true for an unknown codec which allows the server to encode a
better error message to the client. If not supported a 415 error
response could be used to match gRPC server like handling. If not
supported and trying to write an error the ErrorWriter will default to
connects unary encoding (consistent with current behaviour).

Fixes #689
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant