Webserver part-1
Basic Webservice in Golang.
http.ListenAndServe function takes two parameters, addr string and handler.
package main
import "net/http"
func main(){
http.ListenAndServe(":8080", nil)
//addr string can be ip address followed by port.
//Just port signifies that every ip address on the server.
}
Running the above code restirns the following:
curl -v http://localhost:8080
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Mon, 12 Aug 2024 15:42:04 GMT
< Content-Length: 19
<
404 page not found
* Connection #0 to host localhost left intact
Since no request is sent, the server returns a 404. The requests are handled by http.HandleFunc() handler in Golang. We can refer the documentation how http.HandleFunc is used. https://pkg.go.dev/net/http#HandleFunc The implementation of DefaultServeMux can be seen at https://go.dev/src/net/http/server.go The updated code is:
package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(http.ResponseWriter, *http.Request) {
log.Println("hello world")
//This HandleFunc is a convinience method, it takes the function
//and creates a http handler from it and adds it to DefaultServeMux
})
http.ListenAndServe(":8080", nil)
//addr string can be ip address followed by port.
//Just port signifies that every ip address on the server.
//HandleFunc is a convinience method which registers a function to a path on the DefaultServeMux.
//DefaultServeMux is http handler, everything related to server in go is http handler.
//Since the second parameter on ListenAndServe handler is nil, it uses DefaultServeMux.
//When we call ListenAndServe, it uses DefaultServeMux as its root handler and
//determines which code block needs to be executed on the type of request.
}
The above code prints hello world on the server terminal.
Adding a new handler goodbye
package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(http.ResponseWriter, *http.Request) {
log.Println("hello world")
})
http.HandleFunc("/goodbye", func(http.ResponseWriter, *http.Request) {
log.Println("goodbye")
})
http.ListenAndServe(":8080", nil)
}
When the above code is run, the respose goodbye is returned when url is hit with /goodbye. However, when anything else is passed onto the url, it return hello world.
Using ResponseWriter and Request interfacs to read and write to our functions. https://pkg.go.dev/net/http#ResponseWriter https://pkg.go.dev/net/http#Request
Making changes to the HandleFunc taking care of “/” url path. func(rw http.ResponseWriter, r *http.Request)
rw (short for ResponseWriter): Represents the http.ResponseWriter interface, which is used to write the HTTP response back to the client.
r (short for Request): Represents a pointer to an http.Request struct, which contains details about the HTTP request made by the client.
Next we use ioutil ro read the request body.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
log.Println("hello world")
// Adding response writer and request variables to the http handler.
d, err := ioutil.ReadAll(r.Body)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte("Bazinga!"))
//same things can be written replacing the above two lines and using the
//http error package.
//http.Error(rw, "Bazinga!", http.StatusBadRequest)
return
}
fmt.Fprintf(rw, "Hello %s", d)
})
http.HandleFunc("/goodbye", func(http.ResponseWriter, *http.Request) {
log.Println("goodbye")
})
http.ListenAndServe(":8080", nil)
//addr string can be ip address followed by port.
//Just port signifies that every ip address on the server.
}