7.2 net/http包使用及工作原理

一个web应用从客户端(浏览器)发起请求(request)到服务端(服务器),服务端从HTTP Request中提取请求路径(URL)并找到对应的处理程序(Handler)处理请求,最后返回结果。以下讲解为http服务端实现。

http包的运行机制

服务端的几个概念

  • Request:用户请求的信息,用来解析用户的请求信息,包括post,get,Cookie,url等信息。

  • Response:服务器需要反馈给客户端的信息。

  • Conn:用户的每次请求链接。

  • Handle:处理请求和生成返回信息的处理逻辑。

Go实现web服务的流程

  • 创建Listen Socket,监听指定的端口,等待客户端请求到来。
  • Listen Socket接受客户端的请求,得到Client Socket,接下来通过Client Socket与客户端通信。
  • 处理客户端请求,首先从Client Socket读取HTTP请求的协议头,如果是POST方法,还可能要读取客户端提交的数据,然后交给相应的handler处理请求,handler处理完,将数据通过Client Socket返回给客户端。

http 执行流程

net/http包使用及工作原理 - 图1

源码分析(net/http 源码 或本地 src/net/http/server.go)

Go 语言中处理 HTTP 请求主要跟两个东西相关:ServeMux 和 Handler。

ServrMux 本质上是一个 HTTP 请求路由器(或者叫多路复用器,Multiplexor)。它把收到的请求与一组预先定义的 URL 路径列表做对比,然后在匹配到路径的时候调用关联的处理器(Handler)。

处理器(Handler)负责输出HTTP响应的头和正文。任何满足了http.Handler接口的对象都可作为一个处理器。通俗的说,对象只要有个如下签名的ServeHTTP方法即可:

一、注册路由

1、先调用 http.HandleFunc(“/“, sayHelloHandler),方法如下:

  1. func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  2. DefaultServeMux.HandleFunc(pattern, handler)
  3. }

2、使用默认 ServeMux

  1. // HandleFunc registers the handler function for the given pattern.
  2. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  3. mux.Handle(pattern, HandlerFunc(handler))
  4. }

3、注册路由策略 DefaultServeMux

  1. // Handle registers the handler for the given pattern.
  2. // If a handler already exists for pattern, Handle panics.
  3. func (mux *ServeMux) Handle(pattern string, handler Handler) {
  4. mux.mu.Lock()//涉及并发,需要枷锁
  5. defer mux.mu.Unlock()
  6. if pattern == "" {
  7. panic("http: invalid pattern")
  8. }
  9. if handler == nil {
  10. panic("http: nil handler")
  11. }
  12. if _, exist := mux.m[pattern]; exist {
  13. panic("http: multiple registrations for " + pattern)
  14. }
  15. if mux.m == nil {
  16. mux.m = make(map[string]muxEntry)
  17. }
  18. //pattern url 匹配正则
  19. mux.m[pattern] = muxEntry{h: handler, pattern: pattern}
  20. if pattern[0] != '/' {
  21. mux.hosts = true
  22. }
  23. }

二、服务监听

1、调用 http.ListenAndServe(“:8080”, nil) 监听 ,方法代码如下:

  1. // ListenAndServe always returns a non-nil error.
  2. func ListenAndServe(addr string, handler Handler) error {
  3. server := &Server{Addr: addr, Handler: handler}
  4. return server.ListenAndServe()
  5. }

创建一个 Server 对象,并调用 Server 的 ListenAndServe()

2、监听tcp端口 , server.ListenAndServe 对应代码:

  1. // ListenAndServe listens on the TCP network address srv.Addr and then
  2. // calls Serve to handle requests on incoming connections.
  3. // Accepted connections are configured to enable TCP keep-alives.
  4. // If srv.Addr is blank, ":http" is used.
  5. // ListenAndServe always returns a non-nil error.
  6. func (srv *Server) ListenAndServe() error {
  7. addr := srv.Addr
  8. if addr == "" {
  9. addr = ":http"
  10. }
  11. ln, err := net.Listen("tcp", addr)
  12. if err != nil {
  13. return err
  14. }
  15. return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
  16. }

3、接收请求,srv.Serve()对应代码:

  1. // Serve always returns a non-nil error. After Shutdown or Close, the
  2. // returned error is ErrServerClosed.
  3. func (srv *Server) Serve(l net.Listener) error {
  4. defer l.Close()
  5. if fn := testHookServerServe; fn != nil {
  6. fn(srv, l)
  7. }
  8. var tempDelay time.Duration // how long to sleep on accept failure
  9. if err := srv.setupHTTP2_Serve(); err != nil {
  10. return err
  11. }
  12. srv.trackListener(l, true)
  13. defer srv.trackListener(l, false)
  14. baseCtx := context.Background() // base is always background, per Issue 16220
  15. ctx := context.WithValue(baseCtx, ServerContextKey, srv)
  16. for {
  17. rw, e := l.Accept() //接收请求
  18. if e != nil {
  19. select {
  20. case <-srv.getDoneChan():
  21. return ErrServerClosed
  22. default:
  23. }
  24. if ne, ok := e.(net.Error); ok && ne.Temporary() {
  25. if tempDelay == 0 {
  26. tempDelay = 5 * time.Millisecond
  27. } else {
  28. tempDelay *= 2
  29. }
  30. if max := 1 * time.Second; tempDelay > max {
  31. tempDelay = max
  32. }
  33. srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
  34. time.Sleep(tempDelay)
  35. continue
  36. }
  37. return e
  38. }
  39. tempDelay = 0
  40. c := srv.newConn(rw) 创建 *conn
  41. c.setState(c.rwc, StateNew) // before Serve can return
  42. go c.serve(ctx) //新启一个goroutine,将请求数据做为参数传给 conn,由这个新的goroutine 来处理这次请求
  43. }
  44. }

Go为了实现高并发和高性能, 使用了goroutines来处理Conn的读写事件, 这样每个请求都能保持独立,相互不会阻塞,可以高效的响应网络事件。

4、goroutine 处理请求

  1. // Serve a new connection.
  2. func (c *conn) serve(ctx context.Context) {
  3. c.remoteAddr = c.rwc.RemoteAddr().String()
  4. ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
  5. defer func() {
  6. if err := recover(); err != nil && err != ErrAbortHandler {
  7. const size = 64 << 10
  8. buf := make([]byte, size)
  9. buf = buf[:runtime.Stack(buf, false)]
  10. c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
  11. }
  12. if !c.hijacked() {
  13. c.close()
  14. c.setState(c.rwc, StateClosed)
  15. }
  16. }()
  17. if tlsConn, ok := c.rwc.(*tls.Conn); ok {
  18. if d := c.server.ReadTimeout; d != 0 {
  19. c.rwc.SetReadDeadline(time.Now().Add(d))
  20. }
  21. if d := c.server.WriteTimeout; d != 0 {
  22. c.rwc.SetWriteDeadline(time.Now().Add(d))
  23. }
  24. if err := tlsConn.Handshake(); err != nil {
  25. c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
  26. return
  27. }
  28. c.tlsState = new(tls.ConnectionState)
  29. *c.tlsState = tlsConn.ConnectionState()
  30. if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
  31. if fn := c.server.TLSNextProto[proto]; fn != nil {
  32. h := initNPNRequest{tlsConn, serverHandler{c.server}}
  33. fn(c.server, tlsConn, h)
  34. }
  35. return
  36. }
  37. }
  38. // HTTP/1.x from here on.
  39. ctx, cancelCtx := context.WithCancel(ctx)
  40. c.cancelCtx = cancelCtx
  41. defer cancelCtx()
  42. c.r = &connReader{conn: c}
  43. c.bufr = newBufioReader(c.r)
  44. c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
  45. for {
  46. w, err := c.readRequest(ctx)
  47. if c.r.remain != c.server.initialReadLimitSize() {
  48. // If we read any bytes off the wire, we're active.
  49. c.setState(c.rwc, StateActive)
  50. }
  51. if err != nil {
  52. const errorHeaders = "\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\n"
  53. if err == errTooLarge {
  54. // Their HTTP client may or may not be
  55. // able to read this if we're
  56. // responding to them and hanging up
  57. // while they're still writing their
  58. // request. Undefined behavior.
  59. const publicErr = "431 Request Header Fields Too Large"
  60. fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
  61. c.closeWriteAndWait()
  62. return
  63. }
  64. if isCommonNetReadError(err) {
  65. return // don't reply
  66. }
  67. publicErr := "400 Bad Request"
  68. if v, ok := err.(badRequestError); ok {
  69. publicErr = publicErr + ": " + string(v)
  70. }
  71. fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
  72. return
  73. }
  74. // Expect 100 Continue support
  75. req := w.req
  76. if req.expectsContinue() {
  77. if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
  78. // Wrap the Body reader with one that replies on the connection
  79. req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
  80. }
  81. } else if req.Header.get("Expect") != "" {
  82. w.sendExpectationFailed()
  83. return
  84. }
  85. c.curReq.Store(w)
  86. if requestBodyRemains(req.Body) {
  87. registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
  88. } else {
  89. if w.conn.bufr.Buffered() > 0 {
  90. w.conn.r.closeNotifyFromPipelinedRequest()
  91. }
  92. w.conn.r.startBackgroundRead()
  93. }
  94. // HTTP cannot have multiple simultaneous active requests.[*]
  95. // Until the server replies to this request, it can't read another,
  96. // so we might as well run the handler in this goroutine.
  97. // [*] Not strictly true: HTTP pipelining. We could let them all process
  98. // in parallel even if their responses need to be serialized.
  99. // But we're not going to implement HTTP pipelining because it
  100. // was never deployed in the wild and the answer is HTTP/2.
  101. serverHandler{c.server}.ServeHTTP(w, w.req) //处理请求
  102. w.cancelCtx()
  103. if c.hijacked() {
  104. return
  105. }
  106. w.finishRequest()
  107. if !w.shouldReuseConnection() {
  108. if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
  109. c.closeWriteAndWait()
  110. }
  111. return
  112. }
  113. c.setState(c.rwc, StateIdle)
  114. c.curReq.Store((*response)(nil))
  115. if !w.conn.server.doKeepAlives() {
  116. // We're in shutdown mode. We might've replied
  117. // to the user without "Connection: close" and
  118. // they might think they can send another
  119. // request, but such is life with HTTP/1.1.
  120. return
  121. }
  122. if d := c.server.idleTimeout(); d != 0 {
  123. c.rwc.SetReadDeadline(time.Now().Add(d))
  124. if _, err := c.bufr.Peek(4); err != nil {
  125. return
  126. }
  127. }
  128. c.rwc.SetReadDeadline(time.Time{})
  129. }
  130. }

5、处理请求 , serverHandler{c.server}.ServeHTTP(w, w.req)对应代码:

  1. func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
  2. handler := sh.srv.Handler
  3. if handler == nil {
  4. handler = DefaultServeMux
  5. }
  6. if req.RequestURI == "*" && req.Method == "OPTIONS" {
  7. handler = globalOptionsHandler{}
  8. }
  9. handler.ServeHTTP(rw, req)
  10. }

6、handler.ServeHTTP(rw, req)

  1. // ServeHTTP dispatches the request to the handler whose
  2. // pattern most closely matches the request URL.
  3. func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
  4. if r.RequestURI == "*" {
  5. if r.ProtoAtLeast(1, 1) {
  6. w.Header().Set("Connection", "close")
  7. }
  8. w.WriteHeader(StatusBadRequest)
  9. return
  10. }
  11. h, _ := mux.Handler(r)
  12. h.ServeHTTP(w, r)
  13. }

7、执行处理

  1. // The HandlerFunc type is an adapter to allow the use of
  2. // ordinary functions as HTTP handlers. If f is a function
  3. // with the appropriate signature, HandlerFunc(f) is a
  4. // Handler that calls f.
  5. type HandlerFunc func(ResponseWriter, *Request)
  6. // ServeHTTP calls f(w, r).
  7. func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
  8. f(w, r)
  9. }

三、 Handler 函数接受的两个参数:http.Requesthttp.ResponseWriter

1、http.ResponseWriter

ResponseWriter 是一个接口,定义了三个方法:

  • Header():返回一个 Header 对象,可以通过它的 Set() 方法设置头部,注意最终返回的头部信息可能和你写进去的不完全相同,因为后续处理还可能修改头部的值(比如设置 Content-LengthContent-type 等操作)
  • Write(): 写 response 的主体部分,比如 html 或者 json 的内容就是放到这里的
  • WriteHeader():设置 status code,如果没有调用这个函数,默认设置为 http.StatusOK, 就是 200 状态码
  1. // A ResponseWriter interface is used by an HTTP handler to
  2. // construct an HTTP response.
  3. //
  4. // A ResponseWriter may not be used after the Handler.ServeHTTP method
  5. // has returned.
  6. type ResponseWriter interface {
  7. // Header returns the header map that will be sent by
  8. // WriteHeader. The Header map also is the mechanism with which
  9. // Handlers can set HTTP trailers.
  10. //
  11. // Changing the header map after a call to WriteHeader (or
  12. // Write) has no effect unless the modified headers are
  13. // trailers.
  14. //
  15. // There are two ways to set Trailers. The preferred way is to
  16. // predeclare in the headers which trailers you will later
  17. // send by setting the "Trailer" header to the names of the
  18. // trailer keys which will come later. In this case, those
  19. // keys of the Header map are treated as if they were
  20. // trailers. See the example. The second way, for trailer
  21. // keys not known to the Handler until after the first Write,
  22. // is to prefix the Header map keys with the TrailerPrefix
  23. // constant value. See TrailerPrefix.
  24. //
  25. // To suppress implicit response headers (such as "Date"), set
  26. // their value to nil.
  27. Header() Header
  28. // Write writes the data to the connection as part of an HTTP reply.
  29. //
  30. // If WriteHeader has not yet been called, Write calls
  31. // WriteHeader(http.StatusOK) before writing the data. If the Header
  32. // does not contain a Content-Type line, Write adds a Content-Type set
  33. // to the result of passing the initial 512 bytes of written data to
  34. // DetectContentType.
  35. //
  36. // Depending on the HTTP protocol version and the client, calling
  37. // Write or WriteHeader may prevent future reads on the
  38. // Request.Body. For HTTP/1.x requests, handlers should read any
  39. // needed request body data before writing the response. Once the
  40. // headers have been flushed (due to either an explicit Flusher.Flush
  41. // call or writing enough data to trigger a flush), the request body
  42. // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
  43. // handlers to continue to read the request body while concurrently
  44. // writing the response. However, such behavior may not be supported
  45. // by all HTTP/2 clients. Handlers should read before writing if
  46. // possible to maximize compatibility.
  47. Write([]byte) (int, error)
  48. // WriteHeader sends an HTTP response header with the provided
  49. // status code.
  50. //
  51. // If WriteHeader is not called explicitly, the first call to Write
  52. // will trigger an implicit WriteHeader(http.StatusOK).
  53. // Thus explicit calls to WriteHeader are mainly used to
  54. // send error codes.
  55. //
  56. // The provided code must be a valid HTTP 1xx-5xx status code.
  57. // Only one header may be written. Go does not currently
  58. // support sending user-defined 1xx informational headers,
  59. // with the exception of 100-continue response header that the
  60. // Server sends automatically when the Request.Body is read.
  61. WriteHeader(statusCode int)
  62. }

在response中是可以看到

  1. func (w *response) Header() Header
  2. func (w *response) WriteHeader(code ``int``)
  3. func (w *response) Write(data []``byte``) (n ``int``, err error)

所以说response实现了ResponseWriter接口。

2、Request

Request 就是封装好的客户端请求,包括 URL,method,header 等等所有信息,以及一些方便使用的方法:

在源代码 src/net/http/request.go

  1. // The field semantics differ slightly between client and server
  2. // usage. In addition to the notes on the fields below, see the
  3. // documentation for Request.Write and RoundTripper.
  4. type Request struct {
  5. // Method specifies the HTTP method (GET, POST, PUT, etc.).
  6. // For client requests an empty string means GET.
  7. //
  8. // Go's HTTP client does not support sending a request with
  9. // the CONNECT method. See the documentation on Transport for
  10. // details.
  11. Method string
  12. // URL specifies either the URI being requested (for server
  13. // requests) or the URL to access (for client requests).
  14. //
  15. // For server requests the URL is parsed from the URI
  16. // supplied on the Request-Line as stored in RequestURI. For
  17. // most requests, fields other than Path and RawQuery will be
  18. // empty. (See RFC 2616, Section 5.1.2)
  19. //
  20. // For client requests, the URL's Host specifies the server to
  21. // connect to, while the Request's Host field optionally
  22. // specifies the Host header value to send in the HTTP
  23. // request.
  24. URL *url.URL
  25. // The protocol version for incoming server requests.
  26. //
  27. // For client requests these fields are ignored. The HTTP
  28. // client code always uses either HTTP/1.1 or HTTP/2.
  29. // See the docs on Transport for details.
  30. Proto string // "HTTP/1.0"
  31. ProtoMajor int // 1
  32. ProtoMinor int // 0
  33. // Header contains the request header fields either received
  34. // by the server or to be sent by the client.
  35. //
  36. // If a server received a request with header lines,
  37. //
  38. // Host: example.com
  39. // accept-encoding: gzip, deflate
  40. // Accept-Language: en-us
  41. // fOO: Bar
  42. // foo: two
  43. //
  44. // then
  45. //
  46. // Header = map[string][]string{
  47. // "Accept-Encoding": {"gzip, deflate"},
  48. // "Accept-Language": {"en-us"},
  49. // "Foo": {"Bar", "two"},
  50. // }
  51. //
  52. // For incoming requests, the Host header is promoted to the
  53. // Request.Host field and removed from the Header map.
  54. //
  55. // HTTP defines that header names are case-insensitive. The
  56. // request parser implements this by using CanonicalHeaderKey,
  57. // making the first character and any characters following a
  58. // hyphen uppercase and the rest lowercase.
  59. //
  60. // For client requests, certain headers such as Content-Length
  61. // and Connection are automatically written when needed and
  62. // values in Header may be ignored. See the documentation
  63. // for the Request.Write method.
  64. Header Header
  65. // Body is the request's body.
  66. //
  67. // For client requests a nil body means the request has no
  68. // body, such as a GET request. The HTTP Client's Transport
  69. // is responsible for calling the Close method.
  70. //
  71. // For server requests the Request Body is always non-nil
  72. // but will return EOF immediately when no body is present.
  73. // The Server will close the request body. The ServeHTTP
  74. // Handler does not need to.
  75. Body io.ReadCloser
  76. // GetBody defines an optional func to return a new copy of
  77. // Body. It is used for client requests when a redirect requires
  78. // reading the body more than once. Use of GetBody still
  79. // requires setting Body.
  80. //
  81. // For server requests it is unused.
  82. GetBody func() (io.ReadCloser, error)
  83. // ContentLength records the length of the associated content.
  84. // The value -1 indicates that the length is unknown.
  85. // Values >= 0 indicate that the given number of bytes may
  86. // be read from Body.
  87. // For client requests, a value of 0 with a non-nil Body is
  88. // also treated as unknown.
  89. ContentLength int64
  90. // TransferEncoding lists the transfer encodings from outermost to
  91. // innermost. An empty list denotes the "identity" encoding.
  92. // TransferEncoding can usually be ignored; chunked encoding is
  93. // automatically added and removed as necessary when sending and
  94. // receiving requests.
  95. TransferEncoding []string
  96. // Close indicates whether to close the connection after
  97. // replying to this request (for servers) or after sending this
  98. // request and reading its response (for clients).
  99. //
  100. // For server requests, the HTTP server handles this automatically
  101. // and this field is not needed by Handlers.
  102. //
  103. // For client requests, setting this field prevents re-use of
  104. // TCP connections between requests to the same hosts, as if
  105. // Transport.DisableKeepAlives were set.
  106. Close bool
  107. // For server requests Host specifies the host on which the
  108. // URL is sought. Per RFC 2616, this is either the value of
  109. // the "Host" header or the host name given in the URL itself.
  110. // It may be of the form "host:port". For international domain
  111. // names, Host may be in Punycode or Unicode form. Use
  112. // golang.org/x/net/idna to convert it to either format if
  113. // needed.
  114. //
  115. // For client requests Host optionally overrides the Host
  116. // header to send. If empty, the Request.Write method uses
  117. // the value of URL.Host. Host may contain an international
  118. // domain name.
  119. Host string
  120. // Form contains the parsed form data, including both the URL
  121. // field's query parameters and the POST or PUT form data.
  122. // This field is only available after ParseForm is called.
  123. // The HTTP client ignores Form and uses Body instead.
  124. Form url.Values
  125. // PostForm contains the parsed form data from POST, PATCH,
  126. // or PUT body parameters.
  127. //
  128. // This field is only available after ParseForm is called.
  129. // The HTTP client ignores PostForm and uses Body instead.
  130. PostForm url.Values
  131. // MultipartForm is the parsed multipart form, including file uploads.
  132. // This field is only available after ParseMultipartForm is called.
  133. // The HTTP client ignores MultipartForm and uses Body instead.
  134. MultipartForm *multipart.Form
  135. // Trailer specifies additional headers that are sent after the request
  136. // body.
  137. //
  138. // For server requests the Trailer map initially contains only the
  139. // trailer keys, with nil values. (The client declares which trailers it
  140. // will later send.) While the handler is reading from Body, it must
  141. // not reference Trailer. After reading from Body returns EOF, Trailer
  142. // can be read again and will contain non-nil values, if they were sent
  143. // by the client.
  144. //
  145. // For client requests Trailer must be initialized to a map containing
  146. // the trailer keys to later send. The values may be nil or their final
  147. // values. The ContentLength must be 0 or -1, to send a chunked request.
  148. // After the HTTP request is sent the map values can be updated while
  149. // the request body is read. Once the body returns EOF, the caller must
  150. // not mutate Trailer.
  151. //
  152. // Few HTTP clients, servers, or proxies support HTTP trailers.
  153. Trailer Header
  154. // RemoteAddr allows HTTP servers and other software to record
  155. // the network address that sent the request, usually for
  156. // logging. This field is not filled in by ReadRequest and
  157. // has no defined format. The HTTP server in this package
  158. // sets RemoteAddr to an "IP:port" address before invoking a
  159. // handler.
  160. // This field is ignored by the HTTP client.
  161. RemoteAddr string
  162. // RequestURI is the unmodified Request-URI of the
  163. // Request-Line (RFC 2616, Section 5.1) as sent by the client
  164. // to a server. Usually the URL field should be used instead.
  165. // It is an error to set this field in an HTTP client request.
  166. RequestURI string
  167. // TLS allows HTTP servers and other software to record
  168. // information about the TLS connection on which the request
  169. // was received. This field is not filled in by ReadRequest.
  170. // The HTTP server in this package sets the field for
  171. // TLS-enabled connections before invoking a handler;
  172. // otherwise it leaves the field nil.
  173. // This field is ignored by the HTTP client.
  174. TLS *tls.ConnectionState
  175. // Cancel is an optional channel whose closure indicates that the client
  176. // request should be regarded as canceled. Not all implementations of
  177. // RoundTripper may support Cancel.
  178. //
  179. // For server requests, this field is not applicable.
  180. //
  181. // Deprecated: Use the Context and WithContext methods
  182. // instead. If a Request's Cancel field and context are both
  183. // set, it is undefined whether Cancel is respected.
  184. Cancel <-chan struct{}
  185. // Response is the redirect response which caused this request
  186. // to be created. This field is only populated during client
  187. // redirects.
  188. Response *Response
  189. // ctx is either the client or server context. It should only
  190. // be modified via copying the whole Request using WithContext.
  191. // It is unexported to prevent people from using Context wrong
  192. // and mutating the contexts held by callers of the same request.
  193. ctx context.Context
  194. }

Handler 需要知道关于请求的任何信息,都要从这个对象中获取.

net/http包代码执行流程总结


首先调用Http.HandleFunc 按顺序做了几件事: 1 调用了DefaultServeMux的HandleFunc 2 调用了DefaultServeMux的Handle 3 往DefaultServeMux的map[string]muxEntry中增加对应的handler和路由规则

其次调用http.ListenAndServe(“:8080”, 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 判断handler是否为空,如果没有设置handler(这个例子就没有设置handler),handler就设置为DefaultServeMux 8 调用handler的ServeHttp 9 在这个例子中,下面就进入到DefaultServeMux.ServeHttp 10 根据request选择handler,并且进入到这个handler的ServeHTTP mux.handler(r).ServeHTTP(w, r) 11 选择handler: A 判断是否有路由能满足这个request(循环遍历ServerMux的muxEntry) B 如果有路由满足,调用这个路由handler的ServeHttp C 如果没有路由满足,调用NotFoundHandler的ServeHttp

http连接处理流程图

net/http包使用及工作原理 - 图2

links