理解Go/Golang http库的请求解析过程

http是go自带的web开发库,具有非常强大的web开发工程。本文以一个代码为例讲解请求的解析过程。

如下代码为例

func main() {
   http.HandleFunc("/byte", sayByte)
   http.ListenAndServe(":8080", nil)
}

func sayByte(writer http.ResponseWriter, request *http.Request) {
   writer.Write([]byte(" say  byte byte!!"))
}

1. 路由注册

http.HandleFunc("/byte", sayByte)

1.1 此行代码会调用系统默认的ServeMux即DefaultServeMux,DefaultServeMux是http库定义的一个变量。

DefaultServeMux.HandleFunc(pattern, handler)  // serve.go  2380行

1.2 并且利用HandlerFunc将函数sayByte转换成handler,

mux.Handle(pattern, HandlerFunc(handler))  // serve.go 2368行

1.3 真正向DefaultServeMux中注册路由和handler的是ServeMux的handle函数

func (mux *ServeMux) Handle(pattern string, handler Handler) {  //  serve.go 2342
   mux.mu.Lock()
   defer mux.mu.Unlock()

   if pattern == "" {
      panic("http: invalid pattern")
   }
   if handler == nil {
      panic("http: nil handler")
   }
   if _, exist := mux.m[pattern]; exist {
      panic("http: multiple registrations for " + pattern)
   }

   if mux.m == nil {
      mux.m = make(map[string]muxEntry)
   }
   mux.m[pattern] = muxEntry{h: handler, pattern: pattern}

   if pattern[0] != '/' {
      mux.hosts = true
   }
}

1.4 查看ServeMux结构可知,路由和handler存储在ServeMux的m属性中,m是一个map

type ServeMux struct {   //serve.go 2133
   mu    sync.RWMutex
   m     map[string]muxEntry
   hosts bool // whether any patterns contain hostnames
}

到此完成DefaultServeMux的初始化,也就是路由与handler的一一对应关系,存储在一个map中,键是路由,值是muxEntry,而由他存储路由与handler。

2.服务开启

http.ListenAndServe(":8080", nil)

2.1 监听端口

ln, err := net.Listen("tcp", addr) //serve.go 2707

2.2 接受请求

rw, e := l.Accept()  //serve.go 2770

2.3 为请求创建一个连接

c := srv.newConn(rw) //serve.go 2793
2.4 开始服务

go c.serve(ctx)  //serve.go 2795

2.5 初始化ServerHandler,并且调用他的ServeHTTP方法

serverHandler{c.server}.ServeHTTP(w, w.req)  // serve.go //1830

2.6 ServeHttp方法会找出服务的一个ServeMux,如果没有用户自己没有初始化一个ServeMux,则会使用DefaultServeMux,也就是之前默认初始化的ServeMux,最后调用ServeMux的serveHTTP方法。

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { //serve.go 2686
   handler := sh.srv.Handler
   if handler == nil {
      handler = DefaultServeMux
   }
   if req.RequestURI == "*" && req.Method == "OPTIONS" {
      handler = globalOptionsHandler{}
   }
   handler.ServeHTTP(rw, req)
}
2.7 在ServeMux的serveHTTP方法中,找到处理函数并调用

func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {  //serve.go 2328
   if r.RequestURI == "*" {
      if r.ProtoAtLeast(1, 1) {
         w.Header().Set("Connection", "close")
      }
      w.WriteHeader(StatusBadRequest)
      return
   }
   h, _ := mux.Handler(r) //根据url在ServeMux中的m属性中找到处理函数,
   h.ServeHTTP(w, r)  //调用处理函数
}

2.8 寻找处理函数的代码

func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) { /serve.go 2309
   mux.mu.RLock()
   defer mux.mu.RUnlock()

   // Host-specific pattern takes precedence over generic ones
   if mux.hosts {
      h, pattern = mux.match(host + path)  
   }
   if h == nil {
      h, pattern = mux.match(path) 
   }
   if h == nil {
      h, pattern = NotFoundHandler(), ""
   }
   return
}
 
 
func (mux *ServeMux) match(path string) (h Handler, pattern string) { // serve.go 2197
   // Check for exact match first.
   v, ok := mux.m[path]
   if ok {
      return v.h, v.pattern
   }

   // Check for longest valid match.
   var n = 0
   for k, v := range mux.m {
      if !pathMatch(k, path) {
         continue
      }
      if h == nil || len(k) > n {
         n = len(k)
         h = v.h
         pattern = v.pattern
      }
   }
   return
}

注意:观察到ServeMux的m属性的值是muxEntry,结构如下

type muxEntry struct { //serve.go 2139
   h       Handler
   pattern string
}
此处的handler是一个借口,在如下代码中,我们传入的是函数,最终由HandlerFunc将函数转成Handler。

http.HandleFunc("/byte", sayByte)

我们也可以直接实现Handler ,那么此时代码如下

type MyHandler struct{}

func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   fmt.Fprintf(w, "Hello World!")
}
func main() {
   handler := MyHandler{}
   http.Handle("/hello",&handler)
   http.ListenAndServe(":8080",nil)
}

文章到此为止,介绍了

1.ServeMux的初始化过程

2.web请求处理过程

文中如果有错误还请严厉指出。



猜你喜欢

转载自blog.csdn.net/fengxiaozhuzhu/article/details/80920282