Why does request.ParseForm() clears the request.Body?

863 views
Skip to first unread message

OscarRyz

unread,
May 20, 2014, 11:21:43 PM5/20/14
to golan...@googlegroups.com

In this code, if I comment the ParseForm() invocation the request works as expected

package main

import (
    "fmt"
    "net/http"
    "net/url"
    "strings"
)

func main() {

    v := make(url.Values)
    v.Set("status", "yeah!")
    request, error := http.NewRequest("POST", "http://httpbin.org/post", strings.NewReader(v.Encode()))
    if error != nil {
        fmt.Println(error)
    }

    request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
err:=request.ParseForm()
if err != nil {
    fmt.Println(err)    
}
    fmt.Println(request.Form["status"])

    response, error := http.DefaultClient.Do(request)
    if error != nil {
        fmt.Println(error)
    } else {
        fmt.Println(response)
    }
}

But if I call ParseForm() the body is cleared and I get:

Post http://httpbin.org/post: http: Request.ContentLength=14 with Body length 0

Is like the Body length has been drained. How can I access the form values? I need to create a signature of the request. Is there other way to read the form values before the request is sent (other than creating the signature directly from the parameters directly? )

egon

unread,
May 21, 2014, 1:36:33 AM5/21/14
to golan...@googlegroups.com
I'm guessing it's not keeping the Body because it's trying to keep the memory footprint down.

I didn't test this, but something like:

type TeeReadCloser struct {
r Reader
w Writer
}

func (t *TeeReadCloser) Read(p []byte) (n int, err error) {
n, err = t.r.Read(p)
if n > 0 {
if n, err := t.w.Write(p[:n]); err != nil {
return n, err
}
}
return
}

func (t *TeeReadCloser) Close() error {
return r.Close()
}

hash := sha256.New()
request.Body := &TeeReadCloser{request.Body, hash}
err := request.ParseForm()
fmt.Println(hash.Sum())

should work.

+ egon

David Symonds

unread,
May 21, 2014, 3:21:34 AM5/21/14
to OscarRyz, golang-nuts
ParseForm is documented in why it reads the body and where it puts the
parsed form values.

http://golang.org/pkg/net/http/#Request.ParseForm

OscarRyz

unread,
May 21, 2014, 10:59:49 AM5/21/14
to golan...@googlegroups.com, OscarRyz
Mmh I see. I read it several times but I did not understand that "parse" implied the elimination of the body

"... it also parses the request body as a form and put the results into both r.PostForm and r.Form"

But now is clear. Thanks
Reply all
Reply to author
Forward
0 new messages