Branch/Version: Release 5.4.0 (but also master afaik)
Environment: On-prem (Open Source)
Describe the bug
When proxying an HTTP/2 request Tyk gateway does not properly handle receiving a GOAWAY frame from the upstream server, but instead just returns an INTERNAL-error, server closed the stream without sending trailers, which does not properly indicate the client to retry.
Reproduction steps
Steps to reproduce the behavior:
Configure Tyk gateway to support gRPC streaming (enable HTT/2, flush interval etc.)
Add an API
Connect a client to the API with a backend service that uses gRPC server-side streaming
Gracefully shut down the server (it needs to be implemented in a way to send GOAWAY )
Watch the client error & gateway logs
Actual behavior
When the upstream server sends a GOAWAY, Tyk gateway closes the connection to the client with INTERNAL-error, server closed the stream without sending trailers , but internally logs that it received a GOAWAY.
Expected behavior
The gateway should also send a GOAWAY to the client, so it can handle it properly.
Screenshots/Video
n/a
Logs (debug mode or log file):
gateway-tyk-gateway time="Jul 22 08:24:39" level=error msg="http: proxy error during body copy: http2: server sent GOAWAY and closed the connection; LastStreamID=5, ErrCode=NO_ERROR, debug=\"graceful_stop\"" api_id=my-api api_name="My API" mw=ReverseProxy
Configuration (tyk config file):
(no config file, but environment variables from Helm chart; only those added to the chart's defaults)
Looking at the source code, it seems to me that the issue is that the error received from the http2.Transport.RoundTrip() in func (rt *TykRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) (gateway/reverse_proxy.go) just bubbles up to func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Request, withCache bool) ProxyResponse, where there is no distinction made between HTTP/1.1 and HTTP/2, and therefore no special handling for GOAWAY is possible.
Branch/Environment/Version
master
afaik)Describe the bug When proxying an HTTP/2 request Tyk gateway does not properly handle receiving a GOAWAY frame from the upstream server, but instead just returns an
INTERNAL-error, server closed the stream without sending trailers
, which does not properly indicate the client to retry.Reproduction steps Steps to reproduce the behavior:
GOAWAY
)Actual behavior
When the upstream server sends a
GOAWAY
, Tyk gateway closes the connection to the client withINTERNAL-error, server closed the stream without sending trailers
, but internally logs that it received aGOAWAY
.Expected behavior
The gateway should also send a
GOAWAY
to the client, so it can handle it properly.Screenshots/Video
n/a
Logs (debug mode or log file):
Configuration (tyk config file):
(no config file, but environment variables from Helm chart; only those added to the chart's defaults)
Additional context
Looking at the source code, it seems to me that the issue is that the error received from the
http2.Transport.RoundTrip()
infunc (rt *TykRoundTripper) RoundTrip(r *http.Request) (*http.Response, error)
(gateway/reverse_proxy.go
) just bubbles up tofunc (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Request, withCache bool) ProxyResponse
, where there is no distinction made between HTTP/1.1 and HTTP/2, and therefore no special handling forGOAWAY
is possible.