Question

Below is an server written in go.

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
    fmt.Fprintf(w,"%s",r.Method)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

How can I extract the POST data sent to the localhost:8080/something URL?

Was it helpful?

Solution

Like this:

func handler(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()                     // Parses the request body
    x := r.Form.Get("parameter_name") // x will be "" if parameter is not set
    fmt.Println(x)
}

OTHER TIPS

Quoting from the documentation of http.Request

// Form contains the parsed form data, including both the URL
// field's query parameters and the POST or PUT form data.
// This field is only available after ParseForm is called.
// The HTTP client ignores Form and uses Body instead.
Form url.Values

For POST, PATCH and PUT requests:

First we call r.ParseForm() which adds any data in POST request bodies to the r.PostForm map

err := r.ParseForm()
if err != nil {
    // in case of any error
    return
}

// Use the r.PostForm.Get() method to retrieve the relevant data fields
// from the r.PostForm map.
value := r.PostForm.Get("parameter_name")

For POST, GET, PUT and etc (for all requests):

err := r.ParseForm()
if err != nil {
    // in case of any error
    return
}

// Use the r.Form.Get() method to retrieve the relevant data fields
// from the r.Form map.
value := r.Form.Get("parameter_name") // attention! r.Form, not r.PostForm 

The Form method

In contrast, the r.Form map is populated for all requests (irrespective of their HTTP method), and contains the form data from any request body and any query string parameters. So, if our form was submitted to /snippet/create?foo=bar, we could also get the value of the foo parameter by calling r.Form.Get("foo"). Note that in the event of a conflict, the request body value will take precedent over the query string parameter.

The FormValue and PostFormValue Methods

The net/http package also provides the methods r.FormValue() and r.PostFormValue(). These are essentially shortcut functions that call r.ParseForm() for you, and then fetch the appropriate field value from r.Form or r.PostForm respectively. I recommend avoiding these shortcuts because they silently ignore any errors returned by r.ParseForm(). That’s not ideal — it means our application could be encountering errors and failing for users, but there’s no feedback mechanism to let them know.

All samples are from the best book about Go - Let's Go! Learn to Build Professional Web Applications With Golang. This book can answer to all of your questions!

To extract a value from a post request you have to call r.ParseForm() at first. [This][1] parses the raw query from the URL and updates r.Form.

For POST or PUT requests, it also parses the request body as a form and put the results into both r.PostForm and r.Form. POST and PUT body parameters take precedence over URL query string values in r.Form.

Now your r.From is a map of all values your client provided. To extract a particular value you can use r.FormValue("<your param name>") or r.Form.Get("<your param name>").

You can also use r.PostFormValue.

For normal Request:

r.ParseForm()
value := r.FormValue("value")

For multipart Request:

r.ParseForm()
r.ParseMultipartForm(32 << 20)
file, _, _ := r.FormFile("file")
package main

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


func main() {
  // the forward slash at the end is important for path parameters:
  http.HandleFunc("/testendpoint/", testendpoint)
  err := http.ListenAndServe(":8888", nil)
  if err != nil {
    log.Println("ListenAndServe: ", err)
  }
}

func testendpoint(w http.ResponseWriter, r *http.Request) {
  // If you want a good line of code to get both query or form parameters
  // you can do the following:
  param1 := r.FormValue("param1")
  fmt.Fprintf( w, "Parameter1:  %s ", param1)

  //to get a path parameter using the standard library simply
  param2 := strings.Split(r.URL.Path, "/")

  // make sure you handle the lack of path parameters
  if len(param2) > 4 {
    fmt.Fprintf( w, " Parameter2:  %s", param2[5])
  }
}

You can run the code in aapi playground here

Add this to your access url: /mypathparameeter?param1=myqueryparam

I wanted to leave the link above for now, because it gives you a nice place to run the code, and I believe its helpful to be able to see it in action, but let me explain some typical situations where you might want a post argument.

There are a few typical ways developers will pull post data to a back end server, usually multipart form data will be used when pulling files from the request, or large amounts of data, so I don't see how thats relevant here, at least in the context of the question. He is looking for post arguments which typically means form post data. Usually form post arguments are sent in a web form to the back end server.

  1. When a user is submitting a login form or registration data back to golang from html, the Content Type header coming from the client in this case would be application/x-www-form-urlencoded typically, which I believe is what the question is asking, these would be form post arguments, which are extracted with r.FormValue("param1").

  2. In the case of grabbing json from the post body, you would grab the entire post body and unmarshal the raw json into a struct, or use a library to parse the data after you have pulled the data from the request body, Content Type header application/json.

Content Type header is largely responsible for how you will parse the data coming from the client, I have given an example of 2 different content types, but there are many more.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top