对net/http包中server.go源码的简单理解

1. 代码类型

1. 函数类型
2. 结构体类型
3. 接口类型
4. 方法类型
5. 自定义类型

2. 几个比较重要的函数

1. http.HandleFunc(pattern string, handler func(ResponseWriter, *Request))
2. http.ListenAndServe()
3. http.Serve(l net.Listener, handler Handler)
4. http.Handle(pattern string, handler Handler)
5. http.NewServeMux()

3. 几个比较重要的结构体

1. type Server struct
2. type ServeMux struct
3. type muxEntry struct
4. type conn struct
5. type serverHandler struct

4. 几个比较重要的接口

1. type Handler interface
2. type ResponseWriter interface
3. type Flusher interface

5. 几个比较重要的方法

1. func (srv *Server) ListenAndServe() error
2. func (srv *Server) Serve(l net.Listener) error
3. func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
4. func (mux *ServeMux) handler(host, path string)
5. func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
6. func (mux *ServeMux) Handle(pattern string, handler Handler)
7. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) 
8. func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)
9. func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)

6. 一个重要的自定义类型

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
1. type HandlerFunc func(ResponseWriter, *Request)

7. 各类型详细信息


2.1 http.HandleFunc(pattern string, handler func(ResponseWriter, *Request))

// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
} 

2.2 http.ListenAndServe()

// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
// The handler is typically nil, in which case the DefaultServeMux is used.
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}

2.3 http.Serve(l net.Listener, handler Handler)

// Serve accepts incoming HTTP connections on the listener l,
// creating a new service goroutine for each. The service goroutines
// read requests and then call handler to reply to them.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// HTTP/2 support is only enabled if the Listener returns *tls.Conn
// connections and they were configured with "h2" in the TLS
// Config.NextProtos.
//
// Serve always returns a non-nil error.
func Serve(l net.Listener, handler Handler) error {
	srv := &Server{Handler: handler}
	return srv.Serve(l)
}

2.4 http.Handle(pattern string, handler Handler)

// Handle registers the handler for the given pattern
// in the DefaultServeMux.
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }

2.5 http.NewServeMux()

// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux { return new(ServeMux) }

以下结构体类型只列出重要成员
3.1 type Server struct

type Server struct {
   Addr    string  // TCP address to listen on, ":http" if empty
   Handler Handler // handler to invoke, http.DefaultServeMux if nil
   ...
}

3.2 type ServeMux struct

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

3.3 type muxEntry struct

type muxEntry struct {
   h       Handler
   pattern string
}

3.4 type conn struct

type conn struct {
   // server is the server on which the connection arrived.
   // Immutable; never nil.
   server *Server
   // rwc is the underlying network connection.
   // This is never wrapped by other types and is the value given out
   // to CloseNotifier callers. It is usually of type *net.TCPConn or
   // *tls.Conn.
   rwc net.Conn
   ...
}

3.5 type serverHandler struct

// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
	srv *Server
}

4.1 type Handler interface

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

4.2 type ResponseWriter interface

type ResponseWriter interface{
	Header() Header
	Write([]byte) (int, error)
	WriteHeader(statusCode int)
}

4.3 type Flusher interface

type Flusher interface{
	// Flush sends any buffered data to the client.
	Flush()
}

5.1 func (srv *Server) ListenAndServe() error

// ListenAndServe listens on the TCP network address srv.Addr and then
// calls Serve to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// If srv.Addr is blank, ":http" is used.
//
// ListenAndServe always returns a non-nil error. After Shutdown or Close,
// the returned error is ErrServerClosed.
func (srv *Server) ListenAndServe() error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

5.2 func (srv *Server) Serve(l net.Listener) error

// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
//
// HTTP/2 support is only enabled if the Listener returns *tls.Conn
// connections and they were configured with "h2" in the TLS
// Config.NextProtos.
//
// Serve always returns a non-nil error and closes l.
// After Shutdown or Close, the returned error is ErrServerClosed.
func (srv *Server) Serve(l net.Listener) error {
	if fn := testHookServerServe; fn != nil {
		fn(srv, l) // call hook with unwrapped listener
	}

	l = &onceCloseListener{Listener: l}
	defer l.Close()

	if err := srv.setupHTTP2_Serve(); err != nil {
		return err
	}

	if !srv.trackListener(&l, true) {
		return ErrServerClosed
	}
	defer srv.trackListener(&l, false)

	var tempDelay time.Duration     // how long to sleep on accept failure
	baseCtx := context.Background() // base is always background, per Issue 16220
	ctx := context.WithValue(baseCtx, ServerContextKey, srv)
	for {
		rw, e := l.Accept()
		if e != nil {
			select {
			case <-srv.getDoneChan():
				return ErrServerClosed
			default:
			}
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0
		c := srv.newConn(rw)
		c.setState(c.rwc, StateNew) // before Serve can return
		go c.serve(ctx)
	}
}

5.3 func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)

// Handler returns the handler to use for the given request,
// consulting r.Method, r.Host, and r.URL.Path. It always returns
// a non-nil handler. If the path is not in its canonical form, the
// handler will be an internally-generated handler that redirects
// to the canonical path. If the host contains a port, it is ignored
// when matching handlers.
//
// The path and host are used unchanged for CONNECT requests.
//
// Handler also returns the registered pattern that matches the
// request or, in the case of internally-generated redirects,
// the pattern that will match after following the redirect.
//
// If there is no registered handler that applies to the request,
// Handler returns a ``page not found'' handler and an empty pattern.
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {

	// CONNECT requests are not canonicalized.
	if r.Method == "CONNECT" {
		// If r.URL.Path is /tree and its handler is not registered,
		// the /tree -> /tree/ redirect applies to CONNECT requests
		// but the path canonicalization does not.
		if u, ok := mux.redirectToPathSlash(r.URL.Host, r.URL.Path, r.URL); ok {
			return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
		}

		return mux.handler(r.Host, r.URL.Path)
	}

	// All other requests have any port stripped and path cleaned
	// before passing to mux.handler.
	host := stripHostPort(r.Host)
	path := cleanPath(r.URL.Path)

	// If the given path is /tree and its handler is not registered,
	// redirect for /tree/.
	if u, ok := mux.redirectToPathSlash(host, path, r.URL); ok {
		return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
	}

	if path != r.URL.Path {
		_, pattern = mux.handler(host, path)
		url := *r.URL
		url.Path = path
		return RedirectHandler(url.String(), StatusMovedPermanently), pattern
	}

	return mux.handler(host, r.URL.Path)
}

5.4 func (mux *ServeMux) handler(host, path string)

// handler is the main implementation of Handler.
// The path is known to be in canonical form, except for CONNECT methods.
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
	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
}

5.5 func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)

// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
	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
	}
}

5.6 func (mux *ServeMux) Handle(pattern string, handler Handler)

// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
	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
	}
}

5.7 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}

5.8 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

5.9 func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)

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

8. 实现Web服务的方法

最简单的添加Web服务的方法:使用默认路由DefaultSeverMux
第一步 :调用http.HandleFunc("/hello",sayHello)设置访问路由
第二步 :调用http.ListenAndServer(“localhost:8088”,nil)设置端口并开始监听
具体代码如下

package main

import (
	"fmt"
	"net/http"
	"strings"
	"log"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()  //解析参数,默认是不会解析的
	fmt.Println(r.Form)  //这些信息是输出到服务器端的打印信息
	fmt.Println("path", r.URL.Path)
	fmt.Println("scheme", r.URL.Scheme)
	fmt.Println(r.Form["url_long"])
	for k, v := range r.Form {
		fmt.Println("key:", k)
		fmt.Println("val:", strings.Join(v, ""))
	}
	fmt.Fprintf(w, "Hello world!") //这个写入到w的是输出到客户端的
}

func main() {
	http.HandleFunc("/", sayhelloName) //设置访问的路由
	err := http.ListenAndServe("localhost:8088", nil) //设置监听的端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

比较复杂的添加Web服务的方法:使用自定义路由Mux

package main
 
import (
    "fmt"
    "net/http"
)
 
type MyMux struct {
}
 
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path == "/hello" {
        sayHello(w, r)
        return
    }
    http.NotFound(w, r)
    return
}
 
func sayHello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello world!")
}

func main() {
    mux := &MyMux{}
    http.ListenAndServe("localhost:8088", mux)//此处使用自定义的路由
}

更复杂添加Web服务的方法:使用自定义路由,使用http.Server结构体的方法监听服务

type MyServerMux struct {
		Database        string
		RetentionPolicy string
		Logger        *zap.Logger
		Config           *Config
		stats         *Statistics
}

func (mux *MyServerMux ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.URL.Path {
	case "/api/metadata/put":
		w.WriteHeader(http.StatusNoContent)
	case "/api/put":
		mux .servePut(w, r)
	default:
		http.NotFound(w, r)
	}
}

func (mux *MyServerMux) servePut(w http.ResponseWriter, r *http.Request){
......
}

// serveHTTP handles connections in HTTP format.
func (s *Service) serveHTTP() {
	myServerMux := &MyServerMux {
		Database:        s.Database,
		RetentionPolicy: s.RetentionPolicy,
		Logger:          s.Logger,
		stats:           s.stats,
	}
	srv := &http.Server{Handler: myServerMux }//myServerMux 实现了Handler接口的ServeHTTP方法,是该接口的实现
	srv.Serve(s.httpln)//此处的httpln实现了Listener接口的所有方法,是该接口的实现,传入之前需要设置地址
}

另一种做法是:将最后两行换成调用http.ListenAndServer(“localhost:8088”,myServerMux)。但实际上ListenAndServer(“localhost:8088”,myServerMux)调用的是func (srv *Server) ListenAndServe() error,如下

func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}//此处根据传递的地址参数addr和handler,构造Server的实例,由实例调用ListenAndServe()方法

func (srv *Server) ListenAndServe()如下

func (srv *Server) ListenAndServe() error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}
	ln, err := net.Listen("tcp", addr)//由实例传进来的地址开启监听服务
	if err != nil {
		return err
	}
	return  srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})//等待客户端连接
}

可以看到,最后还是调用func (srv *Server) Serve(l net.Listener) error方法。
还有一种做法是:将最后两行换成http.Serve(s.httpln, s.Handler)。而该函数实际上是调用Server的func (srv *Server) Serve(l net.Listener)方法。

func Serve(l net.Listener, handler Handler) error {
	srv := &Server{Handler: handler}
	return srv.Serve(l)
}
func (srv *Server) Serve(l net.Listener) error {
	if fn := testHookServerServe; fn != nil {
		fn(srv, l) // call hook with unwrapped listener
	}

	l = &onceCloseListener{Listener: l}
	defer l.Close()

	if err := srv.setupHTTP2_Serve(); err != nil {
		return err
	}

	if !srv.trackListener(&l, true) {
		return ErrServerClosed
	}
	defer srv.trackListener(&l, false)

	var tempDelay time.Duration     // how long to sleep on accept failure
	baseCtx := context.Background() // base is always background, per Issue 16220
	ctx := context.WithValue(baseCtx, ServerContextKey, srv)
	for {
		rw, e := l.Accept()
		if e != nil {
			select {
			case <-srv.getDoneChan():
				return ErrServerClosed
			default:
			}
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0
		c := srv.newConn(rw)
		c.setState(c.rwc, StateNew) // before Serve can return
		go c.serve(ctx)
	}
}

所以这种方法,最后也是调用func (srv *Server) Serve(l net.Listener) error。
但是在调用func (srv *Server) Serve(l net.Listener) error之前,需要在实例化Server之前先传递一个路由器进来,如果没有传递,那么就是使用默认的路由器DefaultServeMux。如下所示。

func (c *conn) serve(ctx context.Context){}

对net/http包中server.go源码的简单理解

对net/http包中server.go源码的简单理解

默认的Handler的ServeHTTP方法如下。
对net/http包中server.go源码的简单理解

9. 总结一下http包的代码执行流程

通过对http包的分析之后,现在让我们来梳理一下整个的代码执行过程。
当我们使用默认的DefaultServeMux路由器时

  1. 首先调用Http.HandleFunc ,按顺序做了几件事:
    1. 调用了DefaultServeMux的HandleFunc
    2. 调用了DefaultServeMux的Handle
    3. 往DefaultServeMux的map[string]muxEntry中增加对应的handler和路由规则
  2. 其次调用http.ListenAndServe(":9090", nil), 按顺序做了几件事情:
    1. 实例化Server
    2. 调用Server的ListenAndServe()
    3. 调用net.Listen(“tcp”, addr)监听端口
    4. 启动一个for循环,在循环体中Accept请求
    5. 对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务go c.serve()
    6. 读取每个请求的内容w, err := c.readRequest()
    7. 调用serverHandler{c.server}.ServeHTTP(w, w.req)方法
    8. 判断handler是否为空,如果没有设置handler(这个例子就没有设置handler),handler就设置为DefaultServeMux
    9. 调用handler的ServeHTTP
      以下是DefaultServerMux的ServeHTTP方法
      对net/http包中server.go源码的简单理解
      可知需要根据request选择handler。此处选择出来的handler实际上是调用http.HandleFunc("/hello",sayHello)时,传递进去的sayHello函数名。而该函数到底层被类型转换成了HandlerFunc类型,该类型实现了Handler接口的ServeHTTP函数,所以该类型属于Handler接口的子类。
      对net/http包中server.go源码的简单理解
      对net/http包中server.go源码的简单理解
      可知DefaultServerMux选择handler流程如下:
      A 判断是否有路由能满足这个request(循环遍历ServerMux的muxEntry)
      B 如果有路由满足,调用这个路由handler的ServeHttp
      C 如果没有路由满足,调用NotFoundHandler的ServeHttp

当我们使用自定义的路由器时
3. 自定义路由器myMux,结构体类型,在结构体中定义所需变量。
4. 实现http.Handler接口的ServeHTTP()方法。
5. 自定义func(ResponseWriter, *Request)类型函数。
6. 在实现的ServeHTTP()方法中,根据r.URL.Path做分发。
7. 利用自定义的路由器myMux,实例化http.Server对象srv。
8. 设置监听端口net.Listener相关信息ln。
9. 利用对象srv调用Serve()方法,开启监听端口。srv.Serve(ln)。
10. 启动一个for循环,在循环体中Accept请求。
11. 对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务go c.serve()。
12. 读取每个请求的内容w, err := c.readRequest()。
13. 调用serverHandler{c.server}.ServeHTTP(w, w.req)方法。//此时ServeHTTP是serverHandler结构体的方法
14. 判断handler是否为空,如果没有设置handler(这个例子就没有设置handler),handler就设置为DefaultServeMux,否则,就是当前的handler。
15. 调用handler的ServeHTTP。//也即第5步中传入的路由器myMux的ServeHTTP方法
16. 具体的操作因具体路由器的ServeHTTP方法而异。//其实每一个路由器都是Handle接口的子类。因为都实现了ServeHTTP方法。

吐槽一下,看源码好难真**累。