Http requests are a stateless communication model that may sound confusing to beginners.Statelessness here means that each request is independent and independent of each other.Each request is not affected by the last request.
Provide two components in the net/http module to handle Http requests.
ServeMux
ServeMux is a multiplexer (or simple HTTP request router) that can be used in
Find the corresponding resource in the predefined URI resource list and return it to the client.
We create a public folder in the project directory where we can simply create about.html
Create a static service
package main import( "net/http" ) func main() { mux := http.NewServeMux() fs := http.FileServer(http.Dir("public")) mux.Handle("/", fs) http.ListenAndServe(":8080", mux) }
Here we first create a ServeMux service from http.NewServeMux.
Then use FileServer to create a processor that accesses the contents under the public folder.
Mux.Handle ('/', fs) routes us/uses the corresponding FS processor for processing.
Finally, we define our file service on port 8080.
The ListenAndServe function listens for a TCP network address and then calls a service with a defined processor to process requests from that address.The second argument to ListenAndServe is an http.handler, where a servemux object is passed in as the port handling.ServeMux also has a serveHttp method, so it also satisfies the http.handler interface, so you can pass the ServeMux object as the second argument to the ListenAndServe function.ServeMux is actually an implementation of the HTTP.handler interface.
[http://localhost:8080/about.html](http://localhost:8080/about.html)
Custom Processor
Of course, each route can be handled differently depending on your needs. Now let's show you how to customize the processor that handles routes by using an example.
First, let's define the structure of a message. We need to feed back different content based on different routes the user enters.
type messageHandler struct{ message string }
If we allow our message body to process routes, we need to implement ServeHTTP, the interface ServeHTTP(w http.ResponseWriter, r *http.Request), which is two parameters that people who must have network development experience should not be unfamiliar with, especially those who are familiar with nodejs.
func (m *messageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, m.message) }
This allows us to return our messages as strings to the client through the line fmt.Fprintf(w, m.message).
The complete code is as follows
package main import( "net/http" "fmt" "log" ) type messageHandler struct{ message string } func (m *messageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, m.message) } func main() { mux := http.NewServeMux() welcomeHandler := &messageHandler{ "welcome to zidea", } mux.Handle("/welcome",welcomeHandler) angularTutHandler := &messageHandler{ "angular basic tut", } mux.Handle("/angular",angularTutHandler) log.Println("Listening...") http.ListenAndServe(":8080",mux) }
Function Processor
You may find that we all process routes by passing in a function in the flask frameworks of nodejs and python. Do we need to define a structure in go language, and then let it implement a function?
You can convert functions to HandlerFunc by
func welcomeHandlerFunc(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "welcome to zidea") } func main() { mux := http.NewServeMux() welcomeHandler := http.HandlerFunc(welcomeHandlerFunc) mux.Handle("/welcome",welcomeHandler) log.Println("Listening...") http.ListenAndServe(":8080",mux) }
When the parameter of the function is (http.responsewriter, http.request).HandlerFunc can act as an adapter to convert this function into an HTTP handler.The reason is that there is a built-in method ServeHTTP (http.responsewriter, http.request) in the handlerFunc type, so there are enough http.handler interfaces to work as HTTP handlers.
We further optimized that each of our routing corresponding routing processors now returns messages based on routes. We can see that they have common points. If they have common points, we can integrate them into a function that supports closures in the go language. Define a function, messageHandler, to accept a message, and then return to an http.Handler interface.Section We pass a closure to http.HandlerFunc.
func messageHandler(message string) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, message) }) } func main() { mux := http.NewServeMux() mux.Handle("/welcome",messageHandler("welcome to zidea")) mux.Handle("/angular",messageHandler("angular basic tut")) log.Println("Listening...") http.ListenAndServe(":8080",mux) }
Custom Server
In the previous example, http.ListenAndServe was used to run the HTTP service, using the default HTTP service configuration if we want to customize the HTTP server configuration.The HTTP package provides a structure called Server through which we can customize the configuration of the HTTP server.
type Server struct { Addr string Handler Handler ReadTimeout time.Duration WriteTimeout time.Duration MaxHeaderBytes int TLSConfig *tls.Config TLSNextProto map[string]func(*Server, *tls.Conn, Handler) ConnState func(net.Conn, ConnState) ErrorLog *log.Logger }
import( "net/http" "fmt" "log" "time" ) func messageHandler(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "welcome to zidea") } func main() { http.HandleFunc("/welcome", messageHandler) server := &http.Server{ Addr: ":8080", ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } log.Println("Listening...") server.ListenAndServe() }
Reference to the book Web Development with Go