How to make a http url form encoded request in Golang

A POST request is typically sent via a HTML web form and there may be different content types which you can use to send such request. Let’s see the various types you can use when sending a POST request via HTML form


In this article we are going to see how to send a POST request using a application/x-www-form-urlencoded content type using Golang.
Creating a url form encoded request in Golang is straightforward especially when using the methods that comes directly from Go’s standard library.

One of the key struct we are going to use for this is url,Values

Values maps a string key to a list of values. It is typically used for query parameters and form values. Unlike in the http.Header map, the keys in a Values map are case-sensitive.

This is a simple way we can wrap up different key-value pairs together when building a url formencoded POST request. This is particularly easy because the url package provides already an Encode method which we can use out of the box to percent encode our key-value pairs url.Values.Encode()

func (v Values) Encode() string
        

Encode encodes the values into “URL encoded” form (“bar=baz&foo=quux”) sorted by key.

URL form encoded request example

Now let’s see a concrete example on how we can send a url form encoded request in Go (Golang)


package main

import (
    "net/http"
    "net/url"
    "strconv"
    "strings"
    "log"
    "io/ioutil"
)

func main() {
    endpoint := "http://example.com/submit_form.php"
    data := url.Values{}
    data.Set("foo", "bar")
    data.Set("bar", "baz")

    client := &http.Client{}
    r, err := http.NewRequest("POST", endpoint, strings.NewReader(data.Encode())) // URL-encoded payload
    if err != nil {
        log.Fatal(err)
    }
    r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

    res, err := client.Do(r)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(res.Status)
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(string(body))
}
        

Got Questions? Join our Slack community