参考:
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/03.4.md(谢孟军:http包详解)
核心底层方法
启动服务
//开始
http.ListenAndServe(":3000",nil) //代理server.ListenAndServe()
l, err := net.Listen("tcp", addr)
srv.Serve(l)
//监听
for {
rw, err := l.Accept() //conn句柄流
c := srv.newConn(rw) //conn结构体
go c.serve(connCtx) //每个连接对应一个协程处理
}
//解析
for {
w, err := c.readRequest(ctx) //创建请求和响应结构体
req := w.req //请求
serverHandler{c.server}.ServeHTTP(w, w.req) //交给http应用逻辑
}
核心接口和结构体
//tcp总连接
type TCPListener struct {
fd *netFD
lc ListenConfig
}
//连接处理函数
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
//构成一个服务
type Server struct {
Addr string
Handler Handler
mu sync.Mutex
}
//一个具体的tcp连接
func (ln *TCPListener) accept() (*TCPConn, error) {
fd, err := ln.fd.accept()
if err != nil {
return nil, err
}
tc := newTCPConn(fd)
if ln.lc.KeepAlive >= 0 {
setKeepAlive(fd, true)
ka := ln.lc.KeepAlive
if ln.lc.KeepAlive == 0 {
ka = defaultTCPKeepAlive
}
setKeepAlivePeriod(fd, ka)
}
return tc, nil
}
//一个具体的http连接
type conn struct {
server *Server
cancelCtx context.CancelFunc
rwc net.Conn
remoteAddr string
tlsState *tls.ConnectionState
werr error
r *connReader
bufr *bufio.Reader
bufw *bufio.Writer
lastMethod string
curReq atomic.Value // of *response (which has a Request in it)
curState struct{ atomic uint64 } // packed (unixtime<<8|uint8(ConnState))
mu sync.Mutex
hijackedv bool
} //构建一个具体的http请求
req, err := readRequest(c.bufr, keepHostHeader)
readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err error) {
tp := newTextprotoReader(b)
req = new(Request)
s, err = tp.ReadLine()
req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s) //首行
mimeHeader, err := tp.ReadMIMEHeader()//头部
req.Header = Header(mimeHeader)
readTransfer(req, b) //请求体 ,这里弄懂需要查找专门的逻辑
} //默认http服务器
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
}
func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock()
if _, exist := mux.m[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
if pattern[0] != '/' {
mux.hosts = true
}
}
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
} //默认兜底处理函数
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
// Helper handlers
func Error(w ResponseWriter, error string, code int) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(code)
fmt.Fprintln(w, error)
}
func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
|
请发表评论