1

I'm getting empty file when I try to read the request body of my HTTP request using Go Gin. On my request I'm sending a file attached to the Request Body (Content Type: application/octet-stream).

Request Headers
Authorization: Bearer XXX
User-Agent: PostmanRuntime/7.29.0
Accept: */*
Postman-Token: XXX
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 12
Content-Type: application/octet-stream
Request Body
src: "Path to my file"

Backend Go code:

bodySize, _ = strconv.ParseInt(c.Request.Header.Get("Content-Length"), 10, 64)
buf := bytes.NewBuffer(make([]byte, 0, bodySize))
_, err = io.Copy(buf, c.Request.Body)
fmt.Println(buf.String())

The print sentence prints empty string but the file is not empty (Content Length is 12).

Loren
  • 333
  • 5
  • 20
  • I don't see anything wrong with your code. can you debug the `bodySize` and request's body to ensure it has some value? – novalagung Apr 27 '22 at 15:44
  • What I can see debugging is that `buf` value is: `[]uint8 len: 0, cap: 12, []` when I initialize it and after the copy changes to: `[]uint8 len: 0, cap: 536, []` but still empty... – Loren Apr 27 '22 at 15:50
  • You need to show a more complete example here. Did you check the errors? What exactly is `[]uint8 len: 0, cap: 536, []` from? What happens if you just use `io.ReadAll`? – JimB Apr 27 '22 at 15:57
  • No errors using `io.Copy` (nil), using `n, err := io.ReadAll(c.Request.Body)` n is `[]` and no errors neither. – Loren Apr 27 '22 at 16:04
  • 1
    that's mean the request body contains no data – novalagung Apr 27 '22 at 16:08
  • 1
    is there any middleware that might potentially read the request body? – novalagung Apr 27 '22 at 16:09
  • What do you mean `n is []`? The `n` value is an integer with the number of bytes copied, not a slice or array. We really need a [mre] to see what exactly you are doing. – JimB Apr 27 '22 at 16:10
  • @novalagung yes, I'm reading it in a middleware before the main function, after the middleware the execution continues with `c.Next()` . In the middleware the reading works fine. – Loren Apr 27 '22 at 16:15
  • @JimB the length is 0 after the reading. – Loren Apr 27 '22 at 16:17
  • 2
    If you already read the body, then of course there is no longer anything to read in the body. – JimB Apr 27 '22 at 16:21

1 Answers1

1

@novalagung yes, I'm reading it in a middleware before the main function, after the middleware the execution continues with c.Next() . In the middleware the reading works fine. –

The http.Request.Body will be empty after you read its content. You will need to store the request body somewhere after being read, so you do not need to read it twice.


Or, there is another alternative workaround, you can put back the content into the req.Body after reading it.

// middleware do read the body
bodyBytes, _ := ioutil.ReadAll(req.Body)
req.Body.Close()  //  must close

// put back the bodyBytes to req.Body
req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

But I do not recommend it!

novalagung
  • 10,905
  • 4
  • 58
  • 82