构建一个HTTP服务器的简单例子
package main import ( "net/http" ) func SayHello(w http.ResponseWriter, req *http.Request) { w.Write([]byte("Hello")) } func main() { http.HandleFunc("/hello", SayHello) http.ListenAndServe(":8001", nil) }
当我们访问 地址IP:8001/hello 就会得到“hello”输出在浏览器上。
我们分析下这是怎么实现的。先看下接口函数ListenAndServe
func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() }
实际上是生成一个Server对象,然后执行Server对象的函数ListenAndServe()。在分析ListenAndServe()之前我们先看下Handler,实际上Handler是个接口
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
在看Request和ResponseWriter
描述请求头的Request
type Request struct { Method string URL *url.URL Proto string // "HTTP/1.0" ProtoMajor int // 1 ProtoMinor int // 0 Header Header Body io.ReadCloser ContentLength int64 TransferEncoding []string Close bool Host string Form url.Values PostForm url.Values MultipartForm *multipart.Form Trailer Header RemoteAddr string RequestURI string TLS *tls.ConnectionState Cancel <-chan struct{} }
描述应答的ResponseWriter
type ResponseWriter interface { // Header returns the header map that will be sent by // WriteHeader. Changing the header after a call to // WriteHeader (or Write) has no effect unless the modified // headers were declared as trailers by setting the // "Trailer" header before the call to WriteHeader (see example). // To suppress implicit response headers, set their value to nil. Header() Header // Write writes the data to the connection as part of an HTTP reply. // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) // before writing the data. If the Header does not contain a // Content-Type line, Write adds a Content-Type set to the result of passing // the initial 512 bytes of written data to DetectContentType. Write([]byte) (int, error) // WriteHeader sends an HTTP response header with status code. // If WriteHeader is not called explicitly, the first call to Write // will trigger an implicit WriteHeader(http.StatusOK). // Thus explicit calls to WriteHeader are mainly used to // send error codes. WriteHeader(int) }
现在我们回到Server类的ListenAndServe()函数
func (srv *Server) ListenAndServe() error { 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)}) }
实际上这个函数只是执行TCP地址监听,然后执行Server函数,我们看下该函数干了什;函数头有解释,大概意思就是监听一个地址,然后接受连接,然后生成一个goroutine读取这个新的连接请求,而是调用handler去处理这个请求
// 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. // Serve always returns a non-nil error. func (srv *Server) Serve(l net.Listener) error { 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(); err != nil { return err } for { rw, e := l.Accept() if e != nil { 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() } }
handler是啥?我们一开始就说明了,实际上它是一个接口,具体怎么实现由客户定义。但是我们的例子中没有传入这样一个handler。那这个handler怎么来呢?我们继续分析,接受客户端连接后,执行
c := srv.newConn(rw) c.setState(c.rwc, StateNew) // before Serve can return go c.serve()
生成一个连接对象,然后执行连接对象的函数server,我们接着分析该函数:
// Serve a new connection. func (c *conn) serve() { c.remoteAddr = c.rwc.RemoteAddr().String() defer func() { if err := recover(); err != nil { 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 { if d := c.server.ReadTimeout; d != 0 { 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 } } c.r = &connReader{r: c.rwc} c.bufr = newBufioReader(c.r) c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10) for { w, err := c.readRequest() 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 { 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. io.WriteString(c.rwc, "HTTP/1.1 431 Request Header Fields Too Large\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n431 Request Header Fields Too Large") c.closeWriteAndWait() return } if err == io.EOF { return // don't reply } if neterr, ok := err.(net.Error); ok && neterr.Timeout() { return // don't reply } var publicErr string if v, ok := err.(badRequestError); ok { publicErr = ": " + string(v) } io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n400 Bad Request"+publicErr) return } // Expect 100 Continue support req := w.req 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 } // 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. serverHandler{c.server}.ServeHTTP(w, w.req) if c.hijacked() { return } w.finishRequest() if !w.shouldReuseConnection() { if w.requestBodyLimitHit || w.closedRequestBodyEarly() { c.closeWriteAndWait() } return } c.setState(c.rwc, StateIdle) } }
该函数开始尝试TLS握手,如果失败,超时则不是TLS连接,则直接读取http请求:
w, err := c.readRequest()
接着生成一个服务对象,执行服务对象的服务函数:
serverHandler{c.server}.ServeHTTP(w, w.req)
我们看下该函数:
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) }
意思很明显,如果handler为空,则赋值一个DefaultServeMux,也就是默认的Handler,然后执行该默认Handler的服务函数来处理请求:
handler.ServeHTTP(rw, req)
下篇我们将分析该默认Handler.
有疑问加站长微信联系(非本文作者)