Gin v1.2 (golang的web框架)源代码 - 启动、接收请求、路由匹配、处理器链、完成请求

RouterGroup、Handlers、goroutine并发

 

// 运行在debug模式
	gin.SetMode(gin.DebugMode)
	{
		switch value {
		case DebugMode, "":
			ginMode = debugCode
		case ReleaseMode:
			ginMode = releaseCode
		case TestMode:
			ginMode = testCode
		default:
			panic("gin mode unknown: " + value)
		}
		if value == "" {
			value = DebugMode
		}
		modeName = value
	}

	// 创建路由,没有任何中间件 Creates a router without any middleware by default
	var engine *Engine = gin.New()
	{
		debugPrintWARNINGNew()
		{
			debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

`)
		}
		engine := &gin.Engine{
			//type RouterGroup struct {
			//	Handlers HandlersChain
			//	basePath string
			//	engine   *Engine // 对engine的依赖
			//	root     bool
			//}
			// 创建 RouterGroup
			RouterGroup: RouterGroup{
				Handlers: nil, // 处理器链
				basePath: "/",
				root:     true, // 是根路由
			},
			// 模版函数
			FuncMap:                template.FuncMap{},
			RedirectTrailingSlash:  true,
			RedirectFixedPath:      false,
			HandleMethodNotAllowed: false,
			ForwardedByClientIP:    true,
			AppEngine:              defaultAppEngine,
			UseRawPath:             false,
			UnescapePathValues:     true,
			MaxMultipartMemory:     defaultMultipartMemory, // 最大Multipart内存数 defaultMultipartMemory = 32 << 20

			//type methodTree struct {
			//	method string
			//	root   *node
			//}
			//type methodTrees []methodTree
			trees:                  make(methodTrees, 0, 9),
			// 渲染引擎分割符
			delims:                 render.Delims{Left: "{{", Right: "}}"},
			secureJsonPrefix:       "while(1);",
		}
		engine.RouterGroup.engine = engine // 对engine的引用
		engine.pool.New = func() interface{} { // 创建
			return engine.allocateContext()
		}
		return engine
	}

	// 文件上传最大的空间
	// Set a lower memory limit for multipart forms (default is 32 MiB)
	engine.MaxMultipartMemory = int64(3) << 20 // 3 MiB 上传的图片最大允许的大小,3MB

	// 中间件 设置到默认的 RouterGroup.Handlers ,没有路由
	{
		// 全局中间件,日志记录器, Global middleware
		// Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
		// By default gin.DefaultWriter = os.Stdout
		engine.Use(gin.Logger())
		{
			engine.RouterGroup.Use(middleware...)
			{
				// group === RouterGroup
				// append 中间件
				group.Handlers = append(group.Handlers, middleware...)

				// group === RouterGroup
				return group.returnObj()
				{
					if group.root {
						return group.engine
					}
					return group
				}
			}
			engine.rebuild404Handlers()
			{
				engine.allNoRoute = engine.combineHandlers(engine.noRoute)
			}
			engine.rebuild405Handlers()
			{
				engine.allNoMethod = engine.combineHandlers(engine.noMethod)
			}
			return engine
		}

		// 中间件,错误处理。Recovery middleware recovers from any panics and writes a 500 if there was one.
		engine.Use(gin.Recovery())

		// 中间件 - api统计
		engine.Use(middleware.APIStatsD())
	}

	// 路由
	{
		//路由写法:
		//	1、必须以“/”开头
		//	2、路由中要参数,只要参数前有“*”或“:”即可
		//"/module0/ctrl0/action0/:param0/:param1/*"
		frontApi := engine.Group("/api", middleware.RefreshTokenCookie) // 创建一个新的 RouterGroup,并设置一个名为“middleware.RefreshTokenCookie”的handler
		{
			// 创建新的RouterGroup
			return &gin.RouterGroup{
				// 把根 group 的 handlers 拷贝出来,并进行合并
				Handlers: group.combineHandlers(handlers){
					finalSize := len(group.Handlers) + len(handlers)
					if finalSize >= int(abortIndex) {
						panic("too many handlers")
					}
					mergedHandlers := make(HandlersChain, finalSize)
					copy(mergedHandlers, group.Handlers)
					copy(mergedHandlers[len(group.Handlers):], handlers)
					return mergedHandlers
				}, // handlers === middleware.RefreshTokenCookie
				// 添加相对路径
				basePath: group.calculateAbsolutePath(relativePath), // relativePath === "/api"
				{
					// return "/api"
					return joinPaths(group.basePath, relativePath)
				}
				// 对engine的引用
				engine:   group.engine,
			}
		}
		// 添加路由
		frontApi.GET("/siteinfo", common.SiteInfo) // 访问地址为 “/api/siteinfo”  等价 engine.addRoute("GET","/api/siteinfo", common.SiteInfo0, common.SiteInfo1)
		{
			return group.handle("GET", relativePath, handlers)
			{
				absolutePath := group.calculateAbsolutePath(relativePath)
				{
					//return "/api/siteinfo"
					return joinPaths(group.basePath, relativePath)
				}
				// 把上级 group 的 handlers 拷贝出来,并进行合并
				handlers = group.combineHandlers(handlers)
				{
					finalSize := len(group.Handlers) + len(handlers)
					if finalSize >= int(abortIndex) {
						panic("too many handlers")
					}
					mergedHandlers := make(HandlersChain, finalSize)
					copy(mergedHandlers, group.Handlers)
					copy(mergedHandlers[len(group.Handlers):], handlers)
					return mergedHandlers
				}
				group.engine.addRoute(httpMethod, absolutePath, handlers)
				{
					// httpMethod === "GET"
					// absolutePath === "/api/siteinfo"
					// handlers === 处理器列表
					assert1(path[0] == '/', "path must begin with '/'")
					assert1(method != "", "HTTP method can not be empty")
					assert1(len(handlers) > 0, "there must be at least one handler")

					debugPrintRoute(method, path, handlers)
					{
						if IsDebugging() {
							nuHandlers := len(handlers)
							handlerName := nameOfFunction(handlers.Last())
							debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers)
						}
					}
					// 按请求方式method归类
					root := engine.trees.get(method)
					if root == nil {
						//type node struct {
						//	path      string
						//	indices   string
						//	children  []*node
						//	handlers  HandlersChain
						//	priority  uint32
						//	nType     nodeType
						//	maxParams uint8
						//	wildChild bool
						//}

						//type methodTree struct {
						//	method string
						//	root   *node
						//}
						root = new(node)
						engine.trees = append(engine.trees, methodTree{method: method, root: root})
					}

					// 添加路由 root === node(type node struct)
					root.addRoute(path, handlers)
					{
						fullPath := path
						n.priority++

						// 计算"参数"数量
						numParams := countParams(path)
						{
							var n uint
							for i := 0; i < len(path); i++ {
								if path[i] != ':' && path[i] != '*' {
									continue
								}
								n++
							}
							if n >= 255 {
								return 255
							}
							return uint8(n)
						}

						// non-empty tree
						if len(n.path) > 0 || len(n.children) > 0 { // !!!!!不是空树!!!!!
						walk:
							for {
								// Update maxParams of the current node
								if numParams > n.maxParams {
									n.maxParams = numParams
								}

								// Find the longest common prefix.
								// This also implies that the common prefix contains no ':' or '*'
								// since the existing key can't contain those chars.
								i := 0
								max := min(len(path), len(n.path))
								for i < max && path[i] == n.path[i] {
									i++
								}

								// Split edge
								if i < len(n.path) { // "新地址"比"已有的地址"短,那么提升为父级节点
									child := node{
										path:      n.path[i:],
										wildChild: n.wildChild,
										indices:   n.indices,
										children:  n.children,
										handlers:  n.handlers,
										priority:  n.priority - 1,
									}

									// Update maxParams (max of all children)
									for i := range child.children {
										if child.children[i].maxParams > child.maxParams {
											child.maxParams = child.children[i].maxParams
										}
									}

									n.children = []*node{&child}
									// []byte for proper unicode char conversion, see #65
									n.indices = string([]byte{n.path[i]})
									n.path = path[:i]
									n.handlers = nil
									n.wildChild = false
								}

								// Make new node a child of this node
								if i < len(path) { // 作为子节点加入
									path = path[i:]

									if n.wildChild {
										n = n.children[0]
										n.priority++

										// Update maxParams of the child node
										if numParams > n.maxParams {
											n.maxParams = numParams
										}
										numParams--

										// Check if the wildcard matches
										if len(path) >= len(n.path) && n.path == path[:len(n.path)] {
											// check for longer wildcard, e.g. :name and :names
											if len(n.path) >= len(path) || path[len(n.path)] == '/' {
												continue walk
											}
										}

										panic("path segment '" + path +
											"' conflicts with existing wildcard '" + n.path +
											"' in path '" + fullPath + "'")
									}

									c := path[0]

									// slash after param
									if n.nType == param && c == '/' && len(n.children) == 1 {
										n = n.children[0]
										n.priority++
										continue walk
									}

									// Check if a child with the next path byte exists
									for i := 0; i < len(n.indices); i++ {
										if c == n.indices[i] {
											i = n.incrementChildPrio(i)
											n = n.children[i]
											continue walk
										}
									}

									// Otherwise insert it
									if c != ':' && c != '*' {
										// []byte for proper unicode char conversion, see #65
										n.indices += string([]byte{c})
										child := &node{
											maxParams: numParams,
										}
										n.children = append(n.children, child)
										n.incrementChildPrio(len(n.indices) - 1)
										n = child
									}
									n.insertChild(numParams, path, fullPath, handlers)
									{
										// 作为子节点加入 ...
									}
									return

								} else if i == len(path) { // Make node a (in-path) leaf
									if n.handlers != nil {
										panic("handlers are already registered for path ''" + fullPath + "'")
									}
									n.handlers = handlers
								}
								return
							}
						} else { // Empty tree !!!!!空树!!!!!
							// numParams === 地址参数数量
							// path === "/api/siteinfo"
							// fullPath === "/api/siteinfo"
							// handlers === 处理器列表
							n.insertChild(numParams, path, fullPath, handlers)
							{
								var offset int // already handled bytes of the path

								// numParams === 地址参数数量
								// find prefix until first wildcard (beginning with ':'' or '*'')
								for i, max := 0, len(path); numParams > 0; i++ {
									c := path[i]
									if c != ':' && c != '*' {
										continue
									}

									// find wildcard end (either '/' or path end)
									end := i + 1
									for end < max && path[end] != '/' {
										switch path[end] {
										// the wildcard name must not contain ':' and '*'
										case ':', '*':
											panic("only one wildcard per path segment is allowed, has: '" +
												path[i:] + "' in path '" + fullPath + "'")
										default:
											end++
										}
									}

									// check if this Node existing children which would be
									// unreachable if we insert the wildcard here
									if len(n.children) > 0 {
										panic("wildcard route '" + path[i:end] +
											"' conflicts with existing children in path '" + fullPath + "'")
									}

									// check if the wildcard has a name
									if end-i < 2 {
										panic("wildcards must be named with a non-empty name in path '" + fullPath + "'")
									}

									if c == ':' { // param
										// split path at the beginning of the wildcard
										if i > 0 {
											n.path = path[offset:i]
											offset = i
										}

										child := &node{
											nType:     param,
											maxParams: numParams,
										}
										n.children = []*node{child}
										n.wildChild = true
										n = child
										n.priority++
										numParams--

										// if the path doesn't end with the wildcard, then there
										// will be another non-wildcard subpath starting with '/'
										if end < max {
											n.path = path[offset:end]
											offset = end

											child := &node{
												maxParams: numParams,
												priority:  1,
											}
											n.children = []*node{child}
											n = child
										}

									} else { // catchAll
										if end != max || numParams > 1 {
											panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
										}

										if len(n.path) > 0 && n.path[len(n.path)-1] == '/' {
											panic("catch-all conflicts with existing handle for the path segment root in path '" + fullPath + "'")
										}

										// currently fixed width 1 for '/'
										i--
										if path[i] != '/' {
											panic("no / before catch-all in path '" + fullPath + "'")
										}

										n.path = path[offset:i]

										// first node: catchAll node with empty path
										child := &node{
											wildChild: true,
											nType:     catchAll,
											maxParams: 1,
										}
										n.children = []*node{child}
										n.indices = string(path[i])
										n = child
										n.priority++

										// second node: node holding the variable
										child = &node{
											path:      path[i:],
											nType:     catchAll,
											maxParams: 1,
											handlers:  handlers,
											priority:  1,
										}
										n.children = []*node{child}

										return
									}
								}

								// insert remaining path part and handle to the leaf
								n.path = path[offset:]
								n.handlers = handlers

							}
							n.nType = root // node 类型为根 path
						}
					}
				}
				return group.returnObj()
				{
					if group.root {
						return group.engine
					}
					return group
				}
			}
		}
		frontApi.POST("/action0", user.Signin)

		adminAPI := engine.Group("/api/admin", middleware.RefreshTokenCookie, middleware.AdminRequired)
		adminAPI.GET("/ctrl0/action0", user.AllList)
		adminAPI.POST("/action1", baidu.PushToBaidu)
	}

	// 运行
	engine.Run(":8080")
	{
		defer func() { debugPrintError(err){
			if err != nil {
				debugPrint("[ERROR] %v\n", err)
				{
					if IsDebugging() {
						log.Printf("[GIN-debug] "+format, values...)
					}
				}
			}
		} }()

		address := resolveAddress(addr)
		{
			switch len(addr) {
			case 0: // 没有配置监听地址
				if port := os.Getenv("PORT"); port != "" {
					debugPrint("Environment variable PORT=\"%s\"", port)
					return ":" + port
				}
				debugPrint("Environment variable PORT is undefined. Using port :8080 by default")
				return ":8080"
			case 1: // 有配置监听地址
				return addr[0]
			default:
				panic("too much parameters")
			}
		}
		debugPrint("Listening and serving HTTP on %s\n", address)
		// 使用 go 核心的 http 库,engine.ServeHTTP(....) 作为处理器
		err = http.ListenAndServe(address, engine)
		{
			// address === ":8080"
			// handler === engine.ServeHTTP(....)
			server := &Server{Addr: addr, Handler: handler}
			return server.ListenAndServe()
			{
				// addr === ":8080"
				addr := srv.Addr
				if addr == "" {
					addr = ":http"
				}
				ln, err := net.Listen("tcp", addr)
				{
					// func Listen(network, address string) (Listener, error)

					addrs, err := DefaultResolver.resolveAddrList(context.Background(), "listen", network, address, nil)
					if err != nil {
						return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: err}
					}
					var l Listener
					switch la := addrs.first(isIPv4).(type) {
					case *TCPAddr:
						l, err = ListenTCP(network, la) // Tcp 类型的监听
					case *UnixAddr:
						l, err = ListenUnix(network, la) // Unix 类型的监听
					default:
						return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: address}}
					}
					if err != nil {
						return nil, err // l is non-nil interface containing nil pointer
					}
					return l, nil
				}
				if err != nil {
					return err
				}
				return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) // func (srv *Server) Serve(l net.Listener)
				{
					//type tcpKeepAliveListener struct {
					//	*net.TCPListener
					//}

					defer l.Close()
					if fn := testHookServerServe; fn != nil {
						fn(srv, l)
					}
					var tempDelay time.Duration // how long to sleep on accept failure

					if err := srv.setupHTTP2_Serve(){
						srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults_Serve)
						return srv.nextProtoErr
					}; err != nil {
						return err
					}

					srv.trackListener(l, true)
					{
						s.mu.Lock()
						defer s.mu.Unlock()
						if s.listeners == nil {
							s.listeners = make(map[net.Listener]struct{})
						}
						if add {
							// If the *Server is being reused after a previous
							// Close or Shutdown, reset its doneChan:
							if len(s.listeners) == 0 && len(s.activeConn) == 0 {
								s.doneChan = nil
							}
							s.listeners[ln] = struct{}{}
						} else {
							delete(s.listeners, ln)
						}
					}
					defer srv.trackListener(l, false)

					baseCtx := context.Background() // base is always background, per Issue 16220
					ctx := context.WithValue(baseCtx, ServerContextKey, srv)
					for {
						// 接受连接
						rw, e := l.Accept()
						{
							return func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
								tc, err := ln.AcceptTCP()
								if err != nil {
									return nil, err
								}
								tc.SetKeepAlive(true)
								tc.SetKeepAlivePeriod(3 * time.Minute)
								return tc, nil
							}
						}
						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 := &conn{ // !!!!!!创建连接 !!!!!!
								server: srv, // ------------------------------------ 对Server的引用
								rwc:    rwc, // 客户端连接
							}
							if debugServerConnections {
								c.rwc = newLoggingConn("server", c.rwc)
							}
							return c
						}
						c.setState(c.rwc, StateNew) // before Serve can return
						{
							srv := c.server
							switch state {
							case StateNew:
								srv.trackConn(c, true)
							case StateHijacked, StateClosed:
								srv.trackConn(c, false)
							}
							c.curState.Store(connStateInterface[state])
							if hook := srv.ConnState; hook != nil {
								hook(nc, state)
							}
						}
						go c.serve(ctx) // ------------------------------------------- 创建例程,在此支持高并发
						{
							// 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)
								}
							}()

							if tlsConn, ok := c.rwc.(*tls.Conn); ok { // c === &conn{  server: srv === Server, rwc:    rwc === 客户端连接 , }
								if d := c.server.ReadTimeout; d != 0 { // c.server === Server
									c.rwc.SetReadDeadline(time.Now().Add(d))
								}
								if d := c.server.WriteTimeout; d != 0 {
									c.rwc.SetWriteDeadline(time.Now().Add(d))
								}
								if err := tlsConn.Handshake(); err != nil {
									c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
									return
								}
								c.tlsState = new(tls.ConnectionState)
								*c.tlsState = tlsConn.ConnectionState()
								if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
									if fn := c.server.TLSNextProto[proto]; fn != nil {
										h := initNPNRequest{tlsConn, serverHandler{c.server}}
										fn(c.server, tlsConn, h)
									}
									return
								}
							}

							// HTTP/1.x from here on.

							ctx, cancelCtx := context.WithCancel(ctx)
							c.cancelCtx = cancelCtx
							defer cancelCtx()

							// !!!!!! c === &conn{  server: srv === Server , rwc:    rwc === 客户端连接 , }
							c.r = &connReader{conn: c} // !!!!!! Reader
							c.bufr = newBufioReader(c.r) // !!!!!! Reader
							c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10) // !!!!!! Writer

							for {

								w, err := c.readRequest(ctx)
								{
									if c.hijacked() {
										return nil, ErrHijacked
									}

									var (
										wholeReqDeadline time.Time // or zero if none
										hdrDeadline      time.Time // or zero if none
									)
									t0 := time.Now()
									if d := c.server.readHeaderTimeout(); d != 0 {
										hdrDeadline = t0.Add(d)
									}
									if d := c.server.ReadTimeout; d != 0 {
										wholeReqDeadline = t0.Add(d)
									}
									c.rwc.SetReadDeadline(hdrDeadline)
									if d := c.server.WriteTimeout; d != 0 {
										defer func() {
											c.rwc.SetWriteDeadline(time.Now().Add(d))
										}()
									}

									c.r.setReadLimit(c.server.initialReadLimitSize())
									if c.lastMethod == "POST" {
										// RFC 2616 section 4.1 tolerance for old buggy clients.
										peek, _ := c.bufr.Peek(4) // ReadRequest will get err below
										c.bufr.Discard(numLeadingCRorLF(peek))
									}
									// 创建 Request 对象
									req, err := readRequest(c.bufr, keepHostHeader)
									{
										tp := newTextprotoReader(b)
										req = new(Request) // ---------------------------- 创建 Request 对象

										// First line: GET /index.html HTTP/1.0
										var s string
										if s, err = tp.ReadLine(); err != nil {
											return nil, err
										}
										defer func() {
											putTextprotoReader(tp)
											if err == io.EOF {
												err = io.ErrUnexpectedEOF
											}
										}()

										var ok bool
										req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
										if !ok {
											return nil, &badStringError{"malformed HTTP request", s}
										}
										if !validMethod(req.Method) { // 是否是支持的方法
											return nil, &badStringError{"invalid method", req.Method}
										}
										rawurl := req.RequestURI // 请求地址
										if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
											return nil, &badStringError{"malformed HTTP version", req.Proto}
										}

										// CONNECT requests are used two different ways, and neither uses a full URL:
										// The standard use is to tunnel HTTPS through an HTTP proxy.
										// It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is
										// just the authority section of a URL. This information should go in req.URL.Host.
										//
										// The net/rpc package also uses CONNECT, but there the parameter is a path
										// that starts with a slash. It can be parsed with the regular URL parser,
										// and the path will end up in req.URL.Path, where it needs to be in order for
										// RPC to work.
										justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/")
										if justAuthority {
											rawurl = "http://" + rawurl
										}

										if req.URL, err = url.ParseRequestURI(rawurl); err != nil { // 解析成功 req.URL 对象
											return nil, err
										}

										if justAuthority {
											// Strip the bogus "http://" back off.
											req.URL.Scheme = ""
										}

										// Subsequent lines: Key: value.
										// 读取 MIME 头
										mimeHeader, err := tp.ReadMIMEHeader()
										if err != nil {
											return nil, err
										}
										// 请求头
										req.Header = Header(mimeHeader)

										// 请求主机
										// RFC 2616: Must treat
										//	GET /index.html HTTP/1.1
										//	Host: www.google.com
										// and
										//	GET http://www.google.com/index.html HTTP/1.1
										//	Host: doesntmatter
										// the same. In the second case, any Host line is ignored.
										req.Host = req.URL.Host
										if req.Host == "" {
											req.Host = req.Header.get("Host") // 获取 Host 信息
										}
										if deleteHostHeader {
											delete(req.Header, "Host")
										}

										fixPragmaCacheControl(req.Header)

										req.Close = shouldClose(req.ProtoMajor, req.ProtoMinor, req.Header, false)

										err = readTransfer(req, b)
										if err != nil {
											return nil, err
										}

										if req.isH2Upgrade() {
											// Because it's neither chunked, nor declared:
											req.ContentLength = -1

											// We want to give handlers a chance to hijack the
											// connection, but we need to prevent the Server from
											// dealing with the connection further if it's not
											// hijacked. Set Close to ensure that:
											req.Close = true
										}
										return req, nil
									}
									if err != nil {
										if c.r.hitReadLimit() {
											return nil, errTooLarge
										}
										return nil, err
									}

									if !http1ServerSupportsRequest(req) {
										return nil, badRequestError("unsupported protocol version")
									}

									c.lastMethod = req.Method // 请求方法
									c.r.setInfiniteReadLimit()

									hosts, haveHost := req.Header["Host"] // 请求头的 Host
									isH2Upgrade := req.isH2Upgrade()
									if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" {
										return nil, badRequestError("missing required Host header")
									}
									if len(hosts) > 1 {
										return nil, badRequestError("too many Host headers")
									}
									if len(hosts) == 1 && !httplex.ValidHostHeader(hosts[0]) {
										return nil, badRequestError("malformed Host header")
									}
									for k, vv := range req.Header {
										if !httplex.ValidHeaderFieldName(k) {
											return nil, badRequestError("invalid header name")
										}
										for _, v := range vv {
											if !httplex.ValidHeaderFieldValue(v) {
												return nil, badRequestError("invalid header value")
											}
										}
									}
									delete(req.Header, "Host") // 删除请求头的 Host

									ctx, cancelCtx := context.WithCancel(ctx)
									req.ctx = ctx
									req.RemoteAddr = c.remoteAddr // 远程
									req.TLS = c.tlsState
									if body, ok := req.Body.(*body); ok {
										body.doEarlyClose = true
									}

									// Adjust the read deadline if necessary.
									if !hdrDeadline.Equal(wholeReqDeadline) {
										c.rwc.SetReadDeadline(wholeReqDeadline)
									}

									w = &response{ // ---------------------------- 创建 response 对象
										// !!!!!! c === &conn{  server: srv === Server , rwc:    rwc === 客户端连接 , }
										conn:          c,
										cancelCtx:     cancelCtx,
										req:           req, //  Request 对象
										reqBody:       req.Body, //  Request的Body对象
										handlerHeader: make(Header),
										contentLength: -1,
										closeNotifyCh: make(chan bool, 1),

										// We populate these ahead of time so we're not
										// reading from req.Header after their Handler starts
										// and maybe mutates it (Issue 14940)
										wants10KeepAlive: req.wantsHttp10KeepAlive(),
										wantsClose:       req.wantsClose(),
									}
									if isH2Upgrade {
										w.closeAfterReply = true
									}
									w.cw.res = w // 对response的引用
									w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
									return w, nil
								}

								if c.r.remain != c.server.initialReadLimitSize() {
									// If we read any bytes off the wire, we're active.
									c.setState(c.rwc, StateActive)
								}
								if err != nil {
									const errorHeaders = "\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\n"

									if err == errTooLarge {
										// Their HTTP client may or may not be
										// able to read this if we're
										// responding to them and hanging up
										// while they're still writing their
										// request. Undefined behavior.
										const publicErr = "431 Request Header Fields Too Large"
										fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
										c.closeWriteAndWait()
										return
									}
									if isCommonNetReadError(err) {
										return // don't reply
									}

									publicErr := "400 Bad Request"
									if v, ok := err.(badRequestError); ok {
										publicErr = publicErr + ": " + string(v)
									}

									fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
									return
								}

								// Expect 100 Continue support
								req := w.req //  Request 对象
								if req.expectsContinue() {
									if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
										// Wrap the Body reader with one that replies on the connection
										req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
									}
								} else if req.Header.get("Expect") != "" {
									w.sendExpectationFailed()
									return
								}

								c.curReq.Store(w)

								if requestBodyRemains(req.Body) {
									registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
								} else {
									if w.conn.bufr.Buffered() > 0 {
										w.conn.r.closeNotifyFromPipelinedRequest()
									}
									w.conn.r.startBackgroundRead()
								}

								// 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.

								//type serverHandler struct {
								//	srv *Server
								//}
								// !!!创建 serverHandler 对象,并调用 ServeHTTP(w, w.req) 方法 !!!
								// w === response 对象
								// w.req === Request 对象
								serverHandler{c.server}.ServeHTTP(w, w.req)
								{
									//func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
										// handler === engine
										handler := sh.srv.Handler
										if handler == nil {
											handler = DefaultServeMux
										}
										if req.RequestURI == "*" && req.Method == "OPTIONS" {
											handler = globalOptionsHandler{}
										}
										// handler === engine
										handler.ServeHTTP(rw, req)
										{
											//func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
											// !!! --------------- 创建上下文  --------------
											c := engine.pool.Get().(*Context) // === engine.allocateContext()
											{
												//type Context struct {
												//	writermem responseWriter
												//	Request   *http.Request  // Request 对象
												//	Writer    ResponseWriter
												//
												//	Params   Params
												//	handlers HandlersChain
												//	index    int8
												//
												//	engine *Engine
												//
												//	// Keys is a key/value pair exclusively for the context of each request.
												//	Keys map[string]interface{}
												//
												//	// Errors is a list of errors attached to all the handlers/middlewares who used this context.
												//	Errors errorMsgs
												//
												//	// Accepted defines a list of manually accepted formats for content negotiation.
												//	Accepted []string
												//}
												return &Context{engine: engine}
											}
											c.writermem.reset(w)
											{
												// c.writermem.reset === responseWriter.reset
												//func (w *responseWriter) reset(writer http.ResponseWriter) {
													w.ResponseWriter = writer // !!!!!! response 对象
													w.size = noWritten
													w.status = defaultStatus
												//}
											}
											c.Request = req // !!!!!! Request 对象
											c.reset()
											{
												c.Writer = &c.writermem // responseWriter 对象
												c.Params = c.Params[0:0]
												c.handlers = nil
												c.index = -1
												c.Keys = nil
												c.Errors = c.Errors[0:0]
												c.Accepted = nil
											}

											engine.handleHTTPRequest(c)
											{
												// c ==== Context 上下文
												//func (engine *Engine) handleHTTPRequest(c *Context) {
													httpMethod := c.Request.Method
													path := c.Request.URL.Path // 如: "/dir0/dir1"
													unescape := false
													if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 { // 使用 RawPath 路径
														path = c.Request.URL.RawPath
														unescape = engine.UnescapePathValues
													}

													// Find root of the tree for the given HTTP method
													t := engine.trees
													for i, tl := 0, len(t); i < tl; i++ {
														if t[i].method == httpMethod { // 判断请求方式,如:"POST"
															root := t[i].root
															// Find route in tree !!! ---------------------------------------------- 查找路由
															handlers, params, tsr := root.getValue(path, c.Params, unescape)
															{
																// func (n *node) getValue(path string, po Params, unescape bool) (handlers HandlersChain, p Params, tsr bool) {
																	p = po
																walk: // Outer loop for walking the tree
																	for {
																		if len(path) > len(n.path) { // "请求地址的长度"大于"路由地址长度"
																			if path[:len(n.path)] == n.path { // 前缀匹配
																				path = path[len(n.path):]
																				// If this node does not have a wildcard (param or catchAll)
																				// child,  we can just look up the next child node and continue
																				// to walk down the tree
																				if !n.wildChild {
																					c := path[0]
																					for i := 0; i < len(n.indices); i++ {
																						if c == n.indices[i] {
																							n = n.children[i]
																							continue walk
																						}
																					}

																					// Nothing found.
																					// We can recommend to redirect to the same URL without a
																					// trailing slash if a leaf exists for that path.
																					tsr = path == "/" && n.handlers != nil
																					return
																				}

																				// handle wildcard child
																				n = n.children[0]
																				switch n.nType {
																				case param:
																					// find param end (either '/' or path end)
																					end := 0
																					for end < len(path) && path[end] != '/' {
																						end++
																					}

																					// save param value
																					if cap(p) < int(n.maxParams) {
																						p = make(Params, 0, n.maxParams)
																					}
																					i := len(p)
																					p = p[:i+1] // expand slice within preallocated capacity
																					p[i].Key = n.path[1:]
																					val := path[:end]
																					if unescape {
																						var err error
																						if p[i].Value, err = url.QueryUnescape(val); err != nil {
																							p[i].Value = val // fallback, in case of error
																						}
																					} else {
																						p[i].Value = val
																					}

																					// we need to go deeper!
																					if end < len(path) {
																						if len(n.children) > 0 {
																							path = path[end:]
																							n = n.children[0]
																							continue walk
																						}

																						// ... but we can't
																						tsr = len(path) == end+1
																						return
																					}

																					if handlers = n.handlers; handlers != nil {
																						return
																					}
																					if len(n.children) == 1 {
																						// No handle found. Check if a handle for this path + a
																						// trailing slash exists for TSR recommendation
																						n = n.children[0]
																						tsr = n.path == "/" && n.handlers != nil
																					}

																					return

																				case catchAll:
																					// save param value
																					if cap(p) < int(n.maxParams) {
																						p = make(Params, 0, n.maxParams)
																					}
																					i := len(p)
																					p = p[:i+1] // expand slice within preallocated capacity
																					p[i].Key = n.path[2:]
																					if unescape {
																						var err error
																						if p[i].Value, err = url.QueryUnescape(path); err != nil {
																							p[i].Value = path // fallback, in case of error
																						}
																					} else {
																						p[i].Value = path
																					}

																					handlers = n.handlers
																					return

																				default:
																					panic("invalid node type")
																				}
																			}
																		} else if path == n.path { // !!!!地址完全匹配 !!!!
																			// We should have reached the node containing the handle.
																			// Check if this node has a handle registered.
																			if handlers = n.handlers; handlers != nil {
																				return
																			}

																			if path == "/" && n.wildChild && n.nType != root {
																				tsr = true
																				return
																			}

																			// No handle found. Check if a handle for this path + a
																			// trailing slash exists for trailing slash recommendation
																			for i := 0; i < len(n.indices); i++ {
																				if n.indices[i] == '/' {
																					n = n.children[i]
																					tsr = (len(n.path) == 1 && n.handlers != nil) ||
																						(n.nType == catchAll && n.children[0].handlers != nil)
																					return
																				}
																			}

																			return
																		}

																		// Nothing found. We can recommend to redirect to the same URL with an
																		// extra trailing slash if a leaf exists for that path
																		tsr = (path == "/") ||
																			(len(n.path) == len(path)+1 && n.path[len(path)] == '/' &&
																				path == n.path[:len(n.path)-1] && n.handlers != nil)
																		return
																	}
																// }
															}
															if handlers != nil {
																c.handlers = handlers // 处理器
																c.Params = params
																c.Next() // !!!! -------------- 执行处理器链条
																{
																	//func (c *Context) Next() {
																		c.index++
																		for s := int8(len(c.handlers)); c.index < s; c.index++ {
																			c.handlers[c.index](c) // !!!! --------------- 执行处理器
																		}
																	//}
																}
																// 写 http 响应头
																c.writermem.WriteHeaderNow()
																{
																	// w === responseWriter
																	if !w.Written() {
																		w.size = 0
																		// w.ResponseWriter === response 对象
																		w.ResponseWriter.WriteHeader(w.status)
																	}
																}
																return
															}
															if httpMethod != "CONNECT" && path != "/" {
																if tsr && engine.RedirectTrailingSlash {
																	redirectTrailingSlash(c)
																	return
																}
																if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) {
																	return
																}
															}
															break
														}
													}

													if engine.HandleMethodNotAllowed { // 被禁止的方法
														for _, tree := range engine.trees {
															if tree.method != httpMethod { // 查找"请求方法不匹配,但是路由匹配"的handler
																if handlers, _, _ := tree.root.getValue(path, nil, unescape); handlers != nil {
																	c.handlers = engine.allNoMethod
																	// default405Body   = []byte("405 method not allowed")
																	serveError(c, 405, default405Body)
																	return
																}
															}
														}
													}
													c.handlers = engine.allNoRoute // 找不到路由
													// default404Body   = []byte("404 page not found")
													serveError(c, 404, default404Body)
													{
														//var mimePlain = []string{MIMEPlain}
														//func serveError(c *Context, code int, defaultMessage []byte) {
														c.writermem.status = code
														c.Next() // !!!! -------------- 执行处理器链条
														if !c.writermem.Written() {
															if c.writermem.Status() == code {
																c.writermem.Header()["Content-Type"] = mimePlain
																c.Writer.Write(defaultMessage)
															} else {
																c.writermem.WriteHeaderNow()
															}
														}
														// }
													}
												//}
											}

											//  放入上下文
											engine.pool.Put(c)
											//}
										}
									//}

								}
								w.cancelCtx()
								if c.hijacked() {
									return
								}
								w.finishRequest()
								if !w.shouldReuseConnection() {
									if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
										c.closeWriteAndWait()
									}
									return
								}
								c.setState(c.rwc, StateIdle)
								c.curReq.Store((*response)(nil))

								if !w.conn.server.doKeepAlives() {
									// We're in shutdown mode. We might've replied
									// to the user without "Connection: close" and
									// they might think they can send another
									// request, but such is life with HTTP/1.1.
									return
								}

								if d := c.server.idleTimeout(); d != 0 {
									c.rwc.SetReadDeadline(time.Now().Add(d))
									if _, err := c.bufr.Peek(4); err != nil {
										return
									}
								}
								c.rwc.SetReadDeadline(time.Time{})
							}
						}
					}
				}
			}
		}
		return
	}

 

你可能感兴趣的:(golang,golang,web,golang,golang,web)