Skip to content

Help: Incompatibility with HTTP/2 #3

@Subilan

Description

@Subilan

There's an endpoint responsible for pushing updates to clients through SSE in one of my projects, which is based on this SSE lib. The endpoint works fine until deployed to a production server with HTTPS configured: The connection is closed after some time with the client error net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) raised in Chrome, which is totally unexpected. No runtime error or panics on server side, though.

I guess this behaviour is due to the connection being closed prematurely for some reason, so I created a new goroutine for sending heartbeats along with the main message goroutine, even if there's already one inside sse. Somehow, I forgot to wrap the select with an infinite for loop, leading me to find the execution time in Gin logs unusually close to some integer, like 7.0000123s if the heartbeat interval was set to 2s. However, the execution time stays at 5.000~s if the heartbeat interval is greater than or equal to 5s. It turns out that the 5s interval is the default writeTimeout configured on the Conn struct.

So here are my findings:

  • The connection is closed, actively by the server, after writeTimeout when some context deadline is reached. The closing might be unexpected for HTTP/2, thus causing net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) to be raised (the request is completed with 200 but the protocol doesn't like it?)
  • The default value for writeTimeout (5s) and heartbeatInterval (15s) results in the connection closed before a heartbeat can actually happen.
  • Workaround can be adjusting heartbeatInterval and writeTimeout to satisfy heartbeatInterval < writeTimeout

Strangely, while the code is not changed at all, none of above happens in my local non-HTTPS environment, where the protocol remains HTTP/1.1. For testing, I configured a self-signed certificate and run Gin with RunTLS and eventually reproduced the error locally.

I think there's something more than what I've found, and the facade can be quite inaccurate. It would be nice if someone could look into it to improve the lib (quite nice to use, btw).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions