-
Notifications
You must be signed in to change notification settings - Fork 8k
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
Calling bind multiple times #216
Comments
I'll take a look into this, I can't guarantee any estimated time just than v0.6. |
Hi guys, I found func bodyReader(req *http.Request) (*bytes.Buffer, error) {
if req.Body == nil {
return nil, errors.New("Error")
}
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return nil, err
}
buff := bytes.NewBuffer(body)
req.Body = ioutil.NopCloser(buff)
return bytes.NewBuffer(body), nil
}
func (_ jsonBinding) Bind(req *http.Request, obj interface{}) error {
buff, _ := bodyReader(req)
decoder := json.NewDecoder(buff)
if err := decoder.Decode(obj); err == nil {
return Validate(obj)
} else {
return err
}
} Test: // issue #216
func TestBindingMultipleTimes(t *testing.T) {
body := bytes.NewBuffer([]byte("{\"foo\":\"bar\"}"))
r := New()
var modelA struct {
A string `json:"foo"`
}
var modelB struct {
B string `json:"foo"`
}
r.POST("/binding/multiple/bind", func(c *Context) {
if !c.Bind(&modelA) {
c.JSON(500, H{"error": "failed to bind first model"})
return
}
if !c.Bind(&modelB) {
c.JSON(500, H{"error": "failed to bind second model"})
return
}
if modelA.A != modelB.B {
debugPrint("%s!=%s", modelA, modelB)
c.JSON(500, H{"error": "failed fields aren't equals"})
return
}
c.JSON(200, H{"parsed": modelB.B})
})
req, _ := http.NewRequest("POST", "/binding/multiple/bind", body)
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Response code should be Ok, was: %d", w.Code)
}
if w.Body.String() != "{\"parsed\":\"bar\"}\n" {
t.Errorf("Response should be {\"parsed\":\"bar\"}, was: %s", w.Body.String())
}
} |
how about this approach? r.Use(func(c *Context) {
var model Model
if c.Bind(&model) {
c.Set("data_model", model)
// use model
}else{
c.AbortWithStatus(400)
}
})
r.POST("/binding/multiple/bind", func(c *Context) {
model := c.MustGet("data_model").(Model)
}) |
It won't work for case when model fields are significantly different i.e body := bytes.NewBuffer([]byte(`{"foo":"bar", "time": 2323793, "name": "GIN"}`))
r := New()
var modelA struct {
A string `json:"foo"`
Name string `json:"name"`
}
var modelB struct {
B string `json:"foo"`
Timestamp int `json:"time"`
} Is it a real case? What do you think? |
I agree that binding multiple times should be possible one way or another, even with explicit and manual buffer refresh, since this will be a very infrequent use case. In the meantime, as a workaround, you could just create a 'parent' model that inherits both A and B var modelAB struct {
modelA
modelB
} Which, if i remember correctly, should bind nicely all variables. Only issue is that then you end up with all data in one but this shouldn't be too much of a problem in most cases. |
Has there been any progress on this? |
I am also in need of a way to bind a request and then also read it again. I could copy it to a |
+1 this would be awesome to patch that ! @manucorporat using the Thank you ! ❤️ |
++ yes would be nice to have this .... there are lot of scenarios where this has uses.... |
+1 |
11 similar comments
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
* Add interface to read body bytes in binding * Add BindingBody implementation for some binding * Fix to use `BindBodyBytesKey` for key * Revert "Fix to use `BindBodyBytesKey` for key" This reverts commit 2c82901. * Use private-like key for body bytes * Add tests for BindingBody & ShouldBindBodyWith * Add note for README * Remove redundant space between sentences
See the implementation #1341 try it in the latest of master branch. |
I want to use it twice, the first one for middleware and the second time in my controller. Any suggestions? |
Follow the answer here https://stackoverflow.com/questions/62736851/go-gin-read-request-body-many-times works well with |
i was trying to implement |
I'm trying to call bind multiple times to bind to two different models during the same request. It only works the first time I call it, it ends up not binding anything the second time. I suspect this is because a buffer is being read and not being reset. Is there a fix or workaround for this?
The text was updated successfully, but these errors were encountered: