http包中serverHandler类型的分析

http包中serverHandler类型的分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
srv *Server
}

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)
}

serverHandler是一个结构体,在结构体中,只有一个字段sv *Server, 这里在实际运行的过程中,保存了最开始创建的Server实例,包好了服务端Ip端口信息,Handler信息等。

serverHandler也实现了http.Handler接口,我们看一下其ServeHTTP方法的实现:

1
handler := sh.srv.Handler

这里是在获取Server实例中的Handler对象,也就是在调用http.ListenAndServe函数,传入的Handler。

1
2
3
if handler == nil {
handler = DefaultServeMux
}

这里判断handler如果为空,就使用默认的handler,ServeMux。

1
handler.ServeHTTP(rw, req)

这里就调用handler的ServeHTTP方法了,要么进入到自定义的handler中,要么进入到ServeMuxhandler中。

接下来我们,我们看一下serverHandler的使用的地方。其实serverHandler是在接收到客户端的请求后,调用Conn的serve方法中使用的。

1
go c.serve(ctx) // 使用goroutines处理我们的请求

Conn的server方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
c.remoteAddr = c.rwc.RemoteAddr().String()
ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
defer func() {
if err := recover(); err != nil && err != ErrAbortHandler {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
}
if !c.hijacked() {
c.close()
c.setState(c.rwc, StateClosed)
}
}()

.....// 省略

// HTTP cannot have multiple simultaneous active requests.[*]
// Until the server replies to this request, it can't read another,
// so we might as well run the handler in this goroutine.
// [*] Not strictly true: HTTP pipelining. We could let them all process
// in parallel even if their responses need to be serialized.
// But we're not going to implement HTTP pipelining because it
// was never deployed in the wild and the answer is HTTP/2.
// 内部的serverHandler结构体,获取Server对象,创建
// serverHandler实例,并调用ServerHTTP方法
serverHandler{c.server}.ServeHTTP(w, w.req)
.....
}

从这个代码中,可以看出,serverHandler起到了承上启下的作用,由于路由到了我们自定义的handler或ServeMux Handler中, 从而路由到我们的实现的Handler函数。

# Go
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×