On Sat, Sep 16, 2023 at 10:02 PM Илья Шипицин <[email protected]> wrote:
> I wonder if there're gRPC test tests similar to h2spec (I couldn't findI am  
> them)

I am not aware of a single binary that could be used as a gRPC test
for proxies. The closest thing that I can think of is examples from
official gRPC libraries. Internally, the Go library runs a Bash script
for CI "Run extra tests" to check the outputs of examples. It can be
seen at https://github.com/grpc/grpc-go/blob/v1.58.1/examples/examples_test.sh
and could be adopted for HAProxy, by overriding the client `-addr`
flag. There are no guarantees that it continues being maintained in
the current format though.

---

But, gRPC is essentially a framework (binary encoding and custom
headers) for object-oriented HTTP/2. My observed issue is an HTTP/2
processing issue by HAProxy, when the frontend client doesn't send an
END_STREAM flag.

When I implement a similar scenario in other languages, the failure
rate is much lower. For example, I pushed a custom Java client to
https://github.com/sigv/grpcopen/tree/main/java that I was testing
with nginx (same HAProxy configuration as my other proof). When this
request succeeds, however, the session state is reported SD--. The
gRPC example to me is simply the most reliable failure, as there is
some timing involved, which I can't seem to yet figure out fully.

To highlight H2 standard (RFC7540), section 8.1 states "the last frame
in the sequence bears an END_STREAM flag". It is however never
clarified if that's a "MUST" or a "SHOULD". The client could be argued
as non-compliant, assuming it is intended as "MUST". Maybe this is the
reason why the h2spec project does not cover such a scenario ("who
would do such a thing").

What is even more important for this issue though, is the last
paragraph of the same section:

   An HTTP response is complete after the server sends -- or the client
   receives -- a frame with the END_STREAM flag set (including any
   CONTINUATION frames needed to complete a header block).  A server can
   send a complete response prior to the client sending an entire
   request if the response does not depend on any portion of the request
   that has not been sent and received.  When this is true, a server MAY
   request that the client abort transmission of a request without error
   by sending a RST_STREAM with an error code of NO_ERROR after sending
   a complete response (i.e., a frame with the END_STREAM flag).
   Clients MUST NOT discard responses as a result of receiving such a
   RST_STREAM, though clients can always discard responses at their
   discretion for other reasons.

To paraphrase, when the backend server sends END_STREAM, the response
is complete and the server is not interested in the request data
anymore. The END_STREAM is a success in the eyes of the H2 spec, and
"clients MUST NOT discard responses as a result" (that is - HAProxy is
expected to send the response to client when END_STREAM). HAProxy
should not treat it as an abrupt close. When the backend server sends
RST_STREAM(NO_ERROR) to abort the connection, HAProxy must simply stop
sending data to the backend server.

I understand there is some complexity with the mux, and tieing H1 into
it. But the H2 spec says the exchange is successful, and the observed
half-close is okay.

Best regards,
Valters Jansons

Reply via email to