1、go中HTTP请求流程
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;
客户端(client)和服务端(server),两个端的交互来自 client 的 request,以及server端的response。所谓的http服务器,主要在于如何接受 client 的 request,并向client返回response。接收request的过程中,最重要的莫过于路由(router),即实现一个Multiplexer器(MUX)。
2、创建一个HTTP服务
在 Go 代码中,只需要一行代码:
func main() {
http.ListenAndServe(":8080", nil)
}
端口号为 8080 的 http 服务就运行起来了, 但目前还处理不了任何请求。
2.1 添加请求路径
func main() {
http.Handle("/index", &CustomerHandler{})
http.ListenAndServe(":8080", nil)
}
type CustomerHandler struct {
}
func (c *CustomerHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
fmt.Println("implement http server by self")
writer.Write([]byte("server echo"))
}
添加了 /index 路径,在这种方式下,需要为每一个请求都定义一个 Handler,然后 Handler 需要实现 ServeHttp 方法。
Handler 是一个请求处理器,我们如果使用这种方式,就需要为每一个请求的 url 实现一个 Handler,这样实现很繁琐。
但我们还有另一个选择,就是使用 HandlerFunc,添加另外一个路径:
func main() {
http.HandleFunc("/index", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("HandleFunc implement"))
})
http.ListenAndServe(":8080", nil)
}
使用这种方式很简洁,值需要实现 HandlerFunc 类型的一个匿名方法就可以了,HandlerFunc 是一个适配器,可以让我们把一个与 ServeHTTP 签名相同的函数作为一个处理器。
Handler 和 HandlerFunc 都是通过 DefaultServeMux 来实现的。 DefaultServeMux 才是上面服务的核心。
在上面的代码,http.ListenAndServe 的第二个参数传入的是 nil,通常情况下,这个参数都是 nil,跟进代码,发现这个参数为 nil 的时候,就是使用 DefaultServeMux 来作为服务端的实现:
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}
|