Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot read request body after ctx.Bind #2681

Open
3 tasks done
hayashikun opened this issue Oct 3, 2024 · 3 comments
Open
3 tasks done

Cannot read request body after ctx.Bind #2681

hayashikun opened this issue Oct 3, 2024 · 3 comments

Comments

@hayashikun
Copy link

Issue Description

I want to get the request body in httpErrorHandler, but I can't.
Once a request body is read by ctx.Bind, it cannot be read afterward.

To read again after reading, the ReaderCloser must be set, but DefaultBinder#BindBody does not do this.

c.Request().Body = io.NopCloser(bytes.NewBuffer(reqBody)) // Reset

What is the best way to do this?

Checklist

  • Dependencies installed
  • No typos
  • Searched existing issues and docs

Expected behavior

Can read the request body after ctx.Bind or in httpErrorHandler

Actual behavior

Cannot read the request body after ctx.Bind

Steps to reproduce

Working code to debug

body1 := ctx.Request().Body
buf1, err := io.ReadAll(body1)
if err == nil {
	println("before: " + string(buf1))
}
ctx.Request().Body = io.NopCloser(bytes.NewBuffer(buf1))

bindErr := ctx.Bind(req)

body2 := ctx.Request().Body
buf2, err := io.ReadAll(body2)
if err == nil {
	println("after: " + string(buf2))
}
ctx.Request().Body = io.NopCloser(bytes.NewBuffer(buf2))

return bindErr

When a POST request is sent with {"aaa": "hoge"}, the following log is output

before: {"aaa": "hoge"}
after:

Version/commit

v4.12.0

@aldas
Copy link
Contributor

aldas commented Oct 3, 2024

Yep, there needs to be c.Request().Body = io.NopCloser(bytes.NewBuffer(buf1)) after bindErr := c.Bind(req) as bind will "readAll" that body again and making sure that the reader of the body is reusable is out of scope of its contract.

@hayashikun
Copy link
Author

hayashikun commented Oct 4, 2024

By reassigning ReaderCloser to Body in DefaultBinder#BindBody, Body can be read afterward.
If this direction is okay, I will send a PR.
What do you think?

@martinyonatann
Copy link
Contributor

In Go, the request body is represented as an io.ReadCloser, which is a stream that can only be read once. Once it’s consumed (e.g., by ctx.Bind()), the body is no longer available for reading. This is a fundamental aspect of streams in Go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants