When building an HTTP server and client, we might need to pass multiple strings as parameters to an HTTP URL. In this tutorial, we will introduce some methods to parse multiple parameters to a string request in Golang.
Building a simple HTTP server (Lab Setup)
If you do not know how to build a simple HTTP server and client, please visit our previous chapter to understand how we can do that in Golang. For demo purposes, let us create a basic HTTP server that will listen on a pre-defined port number. All the requests to the server will be handled by the HelloFun()
which returns a message to the client:
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", Hellofunc)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("Error creating server %s\n", err.Error())
}
}
func Hellofunc(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to GoLinuxcloud server!")
}
We can use enter http://localhost:8080/ into any web browser to test if our server is working or not:
Method 1: Using the fmt.Sprintf () function
func Sprintf(format string, a ...any) string
: Sprintf formats according to a format specifier and returns the resulting string.
If you want to build a request string that does not require encoding, you can simply use the fmt.Sprintf()
function. In the below example, we will see how we can parse multiple strings as parameters to an URL request from the client. We will modify the server a little bit to extract the parameters from the URL request and return them to the client:
The Server:
func Hellofunc(w http.ResponseWriter, r *http.Request) {
returnStr := ""
// iterate over all the query parameters
values := r.URL.Query()
for k, v := range values {
returnStr = returnStr + k + " => " + strings.Join(v, " ") + "\n"
}
// return to client
fmt.Fprintf(w, returnStr)
}
The Client:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
//parse multiple strings as parameters
url := fmt.Sprintf("http://localhost:8080/?name=%s&id=%s&author=%s", "golinuxcloud", "1", "TuanNguyen")
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Output:
name => golinuxcloud
id => 1
author => TuanNguyen
Method 2: Using the net/url package
Package url parses URLs and implements query escaping. To build URLs that need encoding, we can use the net/url
package.
The net/url package with Query() function
func (u *URL) Query() Values
: Query parses RawQuery and returns the corresponding values. It silently discards malformed value pairs. To check errors use ParseQuery.
The example below illustrates how we can use the Query()
function to parse multiple strings to an HTTP get request:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
url := &url.URL{Scheme: "http", Host: "localhost:8080"}
// parse multiple strings to get url
q := url.Query()
q.Add("author", "TuanNguyen")
q.Add("name", "Go Linux Cloud")
url.RawQuery = q.Encode()
client := &http.Client{}
res, err := client.Get(url.String())
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Output:
name => Go Linux Cloud
author => TuanNguyen
The net/url package with url.Values.Encode() function
In the same scenario, as just explored above, we can use a more powerful method to escape multiple fields at once. Using url.Values struct and url.Values.Encode() method. Here’s its definition
type 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.
Let’s see an example with multiple keys to be URL encoded:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
urlRe := &url.URL{Scheme: "http", Host: "localhost:8080"}
// set the Values
v := url.Values{}
v.Set("author", "TuanNguyen")
v.Add("name", "Go Linux Cloud")
v.Add("drink", "C@ffee")
//encode the params
urlRe.RawQuery = v.Encode()
client := &http.Client{}
res, err := client.Get(urlRe.String())
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Output:
author => TuanNguyen
drink => C@ffee
name => Go Linux Cloud
Summary
I hope you enjoyed the article and learned how to parse multiple strings to an HTTP get request string. If your request does not require encoding, simply use the fmt.Sprintf()
function. For more complex situations which need encoding, consider using the net/url
package with multiple functions to help you parse some strings as parameters: the url.Values.Encode()
or url.Query()
function.
References
https://pkg.go.dev/net/url
How to pass multiple values for a single URL parameter?
How to pass multiple strings into a url in http get?