In the previous chapter, we have shown you some examples of working with the HTTP server and client in Golang. The built-in package net/http in Go provides HTTP client and server implementations. We can create GET, POST, PUT, and DELETE requests using the package below. A common use of JSON is to read data from a web server and display the data on a web page. In today's post we will create a simple HTTP server and client, and send a HTTP POST JSON request to the server.
Simple HTTP server and client in GO
The code shown below guides you on how to create your very first HTTP server and client using the net/http
package.
Create HTTP Server
Our server will only have 1 endpoint ("/") which accepts all the request methods (GET, POST, PUT, DELETE, ...). If you want to explore more complex example, you can read our previous chapter:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
: HandleFunc registers the handler function for the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patterns are matched.
package main
import (
"fmt"
"net/http"
)
func homeHandle(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Home page"))
}
func main() {
http.HandleFunc("/", homeHandle)
fmt.Println("Server listenning on port 3000 ...")
fmt.Println(http.ListenAndServe(":3000", nil))
}
Create HTTP Client
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "http://localhost:3000/"
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))
}
Send HTTP POST JSON request in Go
Configure HTTP Client
Follow the below steps to do an HTTP POST JSON DATA request in Go.
- Create an HTTP POST request using
http.NewRequest
. - The first parameter is the HTTP request method i.e., “POST”
- The second parameter is the URL of the post request (localhost in this example).
- And the third parameter in request data i.e., JSON data.
- Set the HTTP request header
Content-Type
asapplication/json
. - Create a client and make the post request using
client.Do(request)
method.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "http://localhost:3000/"
//request method
method := "POST"
var jsonData = []byte(`{
"username": "user1",
"password": "pw1"
}`)
client := &http.Client{}
req, err := http.NewRequest(method, url, bytes.NewBuffer(jsonData))
// set HTTP request header Content-Type
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
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))
}
Configure HTTP Server
For the server, we will create only 1 endpoint for the demo. If the request method is GET, the server will return a string, else if the request is the POST the server will parse the JSON request body to a struct, else return method is not allowed to the client. We store all the usernames and passwords in a map, if the username and password sent from the client is valid, then return "Login successfully".
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func homeHandle(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
w.Write([]byte("Home page"))
case "POST":
var user User
// unmarshall json string to struct
err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
_, ok := userData[user.Username]
if ok {
if userData[user.Username] == user.Password {
w.Write([]byte("Login successfully"))
} else {
w.Write([]byte("Wrong password"))
}
} else {
w.Write([]byte("Can not find this user"))
}
default:
w.Write([]byte("Method not allowed"))
}
}
func main() {
http.HandleFunc("/", homeHandle)
fmt.Println("Server listenning on port 3000 ...")
fmt.Println(http.ListenAndServe(":3000", nil))
}
var userData map[string]string = map[string]string{"user1": "pw1", "user2": "pw2"}
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}
Output:
Login successfully
We can test more request scenarios using the postman:
Summary
This tutorial gives a very basic overview of how to build a straightforward Go web server. In Go, the ideas of marshaling and unmarshalling JSON string were also discussed. Then, we went over a quick setup procedure for sending HTTP POST requests with JSON body to the server.
References
https://pkg.go.dev/net/http
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
https://en.wikipedia.org/wiki/JSON