That's possible, but the rate of occurrence of the issue is low (but painful when it happens), and the costs of starting a new TLS connection for every HTTP request are significant. I'm looking for a better way.
Jim On Tuesday 2 April 2024 at 15:01:30 UTC-6 Sean Liao wrote: > since you already know the server is problematic, you could just set Close > on the original request. > > On Tue, Apr 2, 2024, 15:29 Jim Minter <j...@minter.uk> wrote: > >> Hello, >> >> I was wondering if anyone had any ideas about >> https://github.com/golang/go/issues/21978 ("net/http: no Client API to >> close server connection based on Response") -- it's an old issue, but it's >> something that's biting me currently and I can't see a neat way to solve it. >> >> As an HTTP client, I'm hitting a case where some HTTP server instance >> behind a load balancer breaks and starts returning 500s (FWIW with no body) >> and without the "Connection: close" header. I retry, but I end up reusing >> the same TCP connection to the same broken HTTP instance, so I never hit a >> different backend server and my retry policy is basically useless. >> >> Obviously I need to get the server owner to fix its behavior, but it >> would be great if, as a client, there were a way to get net/http not to >> reuse the connection further, in order to be less beholden to the server's >> behavior. >> >> This happens with both HTTP/1.1 and HTTP/2. >> >> If appropriate, I could live with the request to close the connection >> racing with other new requests to the same endpoint. Getting to the point >> where 2 or 3 requests fail and then the connection is closed is way better >> than having requests fail ad infinitum. >> >> http.Transport.CloseIdleConnections() doesn't solve the problem well (a) >> because it's a big hammer, and (b) because there's no guarantee that the >> connection is idle when CloseIdleConnections() is called. >> >> FWIW I can see in `func (pc *persistConn) readLoop()` there's the >> following test: >> >> ```go >> if resp.Close || rc.req.Close || resp.StatusCode <= 199 || bodyWritable { >> // Don't do keep-alive on error if either party requested a close >> // or we get an unexpected informational (1xx) response. >> // StatusCode 100 is already handled above. >> alive = false >> } >> ``` >> >> I imagine that extending that to `if resp.Close || rc.req.Close || >> resp.StatusCode <= 199 || bodyWritable || resp.StatusCode >= 500 {` might >> probably help this specific case, but I imagine that's an unacceptably >> large behavior change for the rest of the world. >> >> I'm not sure how else this could be done. Does anyone have any thoughts? >> >> Many thanks for the help, >> >> Jim >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/34d597cf-a84c-48eb-b555-537a8768f468n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/34d597cf-a84c-48eb-b555-537a8768f468n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > - sean > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a3d208a6-90c0-42af-9a13-a8f3f0c7b21dn%40googlegroups.com.