Skip to content

Conversation

@duckbrain
Copy link
Contributor

Closes #3725

Prior to this change, the following error could occur with the generated client code when connecting over http2

http2: Transport: cannot retry err [http2: Transport received Server's graceful shutdown GOAWAY] after Request.Body was written; define Request.GetBody to avoid this error 

This PR does as the message suggests and defines Request.GetBody

duckbrain and others added 4 commits July 7, 2025 22:39
… http.Request goadesign#3725 Prior to this change, the following error could occur with the generated client code when connecting over http2 http2: Transport: cannot retry err [http2: Transport received Server's graceful shutdown GOAWAY] after Request.Body was written; define Request.GetBody to avoid this error This commit does as the message suggests and defines Request.GetBody
@raphael
Copy link
Member

raphael commented Jul 25, 2025

This looks great, thank you. The only thing might be to add comments to explain the code, something like:

  1. In the RequestEncoder function (around lines 181-184):

Before:

 enc := new(jsonEncoder) r.Body = enc r.GetBody = enc.GetBody return enc

After:

 enc := new(jsonEncoder) r.Body = enc // GetBody enables request retry on HTTP/2 connections when the server // sends GOAWAY during graceful shutdown. Without GetBody, the HTTP transport // cannot retry because the request body has already been consumed. r.GetBody = enc.GetBody return enc
  1. For the jsonEncoder struct (around lines 185-188):
 Before: type jsonEncoder struct { b []byte r bytes.Reader }

After:

 // jsonEncoder implements io.ReadCloser and provides GetBody functionality // to support HTTP/2 request retries during server graceful shutdown (GOAWAY). type jsonEncoder struct { b []byte // encoded JSON bytes r bytes.Reader // reader for the encoded bytes }
  1. For the GetBody method (around lines 211-215):

Before:

 func (je *jsonEncoder) GetBody() (io.ReadCloser, error) { if len(je.b) == 0 { return nil, errEncodeNotCalled	} return io.NopCloser(bytes.NewReader(je.b)), nil }

After:

 // GetBody returns a new reader of the encoded bytes, enabling request retries. // This is required for HTTP/2 connections to handle server GOAWAY during graceful shutdown. func (je *jsonEncoder) GetBody() (io.ReadCloser, error) { if len(je.b) == 0 { return nil, errEncodeNotCalled	} return io.NopCloser(bytes.NewReader(je.b)), nil }
@duckbrain
Copy link
Contributor Author

Sorry, for the delay. I've now got the comments added and satisfied the CI checks.

@raphael
Copy link
Member

raphael commented Oct 16, 2025

Looks great, thank you!

@raphael raphael merged commit bd2160f into goadesign:v3 Oct 16, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants