Let’s create simple webserver that you can view in your browser using net/http
This function is going to take the request and give responses as well:
func (w http.ResponseWriter, r *http.Request)
The request handler alone can not accept any HTTP connections from the outside. To listen for HTTP Connections, following code will start Go’s default HTTP server and listen for connections on port 80:
http.ListenAndServe(":80", nil)
Example Code:
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
})
// listening on port 80
log.Println("Web Server has started")
http.ListenAndServe(":80", nil)
}
// reference : https://gowebexamples.com/hello-world/
Process Dynamic request
I’m going to parse a parameter or a URL query parameter called token.
r.URL.Query().Get("token")
Serving static assets
create folder named static
and file named index.html
// static/index.html
<html>
<head>
<title> Sean Lim</title>
</head>
<body>
<h2>Website using GO</h2>
</body>
</html>
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s with token: %s\n", r.URL.Path, r.URL.Query().Get("token"))
})
// create file server
fs := http.FileServer(http.Dir("static/"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
// listening on port 80
log.Println("Web Server has started")
http.ListenAndServe(":80", nil)
}
You can create separate function like this as well:
package main
import (
"fmt"
"log"
"net/http"
)
func rootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s with token: %s\n", r.URL.Path, r.URL.Query().Get("token"))
}
func main() {
http.HandleFunc("/", rootHandler)
// create file server
fs := http.FileServer(http.Dir("static/"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
// listening on port 80
log.Println("Web Server has started")
http.ListenAndServe(":80", nil)
}
Routing using gorilla/mux
install the gorilla/mux package:
go get -u github.com/gorilla/mux
Create a new router which is going to handle all the incoming requests and pass it to the various handlers.
package main
import (
"fmt"
"net/http"
// you need to install the package
"github.com/gorilla/mux"
)
func main() {
// create a new router
r := mux.NewRouter()
r.HandleFunc("/books/{title}/page/{page}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
title := vars["title"]
page := vars["page"]
fmt.Fprintf(w, "You've requested the book: %s on page %s\n", title, page)
})
http.ListenAndServe(":80", r)
}
create various handlers
package main
import (
"encoding/json"
"log"
"net/http"
"time"
// you need to install the package
"github.com/gorilla/mux"
)
func healthHandler(w http.ResponseWriter, r *http.Request) {
// print some information
log.Println("Checking application health")
response := map[string]string{
"status": "UP",
// put .String() since the type of map is set as string.
"timestamp": time.Now().String(),
}
// encoding the response "w"
json.NewEncoder(w).Encode(response)
}
func main() {
// create a new router
r := mux.NewRouter()
r.HandleFunc("/health", healthHandler)
log.Fatal(http.ListenAndServe(":80", r))
}
Create a root handler and get status of website
func rootHandler(w http.ResponseWriter, r *http.Request) {
// print http success status
log.Println("Serving the homepage")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Application is up and running")
}
func main() {
r.HandleFunc("/", rootHandler)
}
Create one more function to fetching details of information. I’m going to create a separate package.
// details/details.go
package details
import "os"
func GetHostname() (string, error) {
hostname, err := os.Hostname()
return hostname, err
}
// main.go
// import detail package
details "github.com/sikgyu/go-microservices/details"
func detailsHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Fetching the details")
hostname, err := details.GetHostname()
// if error is not nil, create an exception (panic)
if err != nil {
panic(err)
}
// print hostname if there's no error
fmt.Println(hostname)
}
func main() {
r.HandleFunc("/details", detailsHandler)
}
// details/details.go
// Get preferred outbound ip of this machine
func GetIP() (net.IP, error) {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP, err
}
Get IP address
You can refer to my Github repo.
Let’s serve this as a json response
func detailsHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Fetching the details")
hostname, err := details.GetHostname()
// if error is not nil, create an exception (panic)
if err != nil {
panic(err)
}
// print hostname and IP address if there's no error
IP, _ := details.GetIP()
fmt.Println(hostname, IP)
response := map[string]string{
"hostname": hostname,
"ip": IP.String(),
}
json.NewEncoder(w).Encode(response)
}