Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reuse request body of *http.Request between HTTP middleware handlers?

I use go-chi as HTTP-router, and I want to reuse one method inside another

func Registration(w http.ResponseWriter, r *http.Request) {
    b, err := ioutil.ReadAll(r.Body) // if you delete this line, the user will be created   
    // ...other code

    // if all good then create new user
    user.Create(w, r)
}

...

func Create(w http.ResponseWriter, r *http.Request) {
  b, err := ioutil.ReadAll(r.Body)  
  // ...other code

  // ... there I get the problem with parse JSON from &b
}

user.Create return error "unexpected end of JSON input"

Actually, after I executed ioutil.ReadAll
user.Create ceased to parse JSON,
in r.Body there was an empty array[]how can I fix this problem?

like image 218
batazor Avatar asked Jan 04 '23 03:01

batazor


2 Answers

The outer handler reads the request body to EOF. When the inner handler is called, there's nothing more to read from the body.

To fix the issue, restore the request body with the data read previously in the outer handler:

func Registration(w http.ResponseWriter, r *http.Request) {
    b, err := ioutil.ReadAll(r.Body) 
    // ...other code
    r.Body = ioutil.NopCloser(bytes.NewReader(b))
    user.Create(w, r)
}

The function bytes.NewReader() returns a io.Reader on a byte slice. The function ioutil.NopCloser converts an io.Reader to the io.ReadCloser required for r.Body.

like image 115
Bayta Darell Avatar answered Jan 13 '23 09:01

Bayta Darell


In the end, I was able to recover data in this way:

r.Body = ioutil.NopCloser(bytes.NewBuffer(b))
like image 38
batazor Avatar answered Jan 13 '23 09:01

batazor