How to extract the post arguments in go server
Asked Answered
S

7

24

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?

Somatology answered 12/5, 2013 at 21:2 Comment(0)
H
41

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)
}
Heerlen answered 12/5, 2013 at 22:27 Comment(3)
Just as note this only seems to work for urlencoded and not for multipart form data.Terpene
PS: The docs for this are currently quite poor and lack good examples. golang.org/pkg/net/http Just saying...Fusil
Yeah those kind of PS are not needed.Sidestroke
S
7

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
Satiety answered 12/5, 2013 at 21:8 Comment(1)
could you be more specific with an example please. I am new and I donot understand how to use it.Somatology
F
5

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!

Filch answered 17/5, 2019 at 8:34 Comment(0)
I
3

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.

Inguinal answered 12/6, 2016 at 6:3 Comment(0)
F
1
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.

Flank answered 7/11, 2019 at 8:51 Comment(5)
That is not what OP is asking, he is asking how the POST data can be extracted.Entrap
Edit all this info in to your answer and it will be a better reaction toward OP. A simple code snippet is not sufficient, also link answers are a bit frowned upon because links can go broken/missing.Entrap
Now thats good advice, I edited my answer, and further advice would be helpful. I am new to posting to this form and want to learn.Flank
@Entrap you guys might want to change your statement in here stackoverflow.com/help/how-to-answer in regards to how to answer a question because here it says links are encouraged. To be honest, I think you need links sometimes to help describe. Let me know if I am off base here.Flank
" but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.". I'm only saying that link-only answers are bad.Entrap
E
1

Just wanted to add how to extract the Post arguments in Go server in case you are working with JSON data which often is the case while building an API ...

//...

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)


//While working with JSON in GoLang I prefer using structs so I created the struct here

type JSONData struct {
    // This should contain the expected JSON data
    // <key> <data type> `json: <where to find the data in the JSON` in this case we have
    Name string `json:"name"`
    Age  string `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    decoder := json.NewDecoder(r.Body)
    var data JSONData
    error := decoder.Decode(&data)
    if error != nil {
        fmt.Println("Error occured while decoding the data: ", error)
        return
    }
    fmt.Println("name: \t", data.Name, " \n  age: \t ", data.Age)

}

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

// ...
// and the rest of your codes
Erving answered 14/2, 2023 at 19:50 Comment(0)
O
0

For normal Request:

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

For multipart Request:

r.ParseForm()
r.ParseMultipartForm(32 << 20)
file, _, _ := r.FormFile("file")
Ochone answered 17/5, 2019 at 9:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.