golang 版本:1.12.9
簡單的HTTP伺服器代碼:
在浏覽器輸入“http://127.0.0.1:8000”得到輸出“Hi,Stranger,welcome”;輸入“http://127.0.0.1:8000/test”得到輸出“Hi,Tester”
handler的注冊
handler的相關方法如下:
http使用handler定義請求的路徑以及請求的處理。每個handler都必須實作ServeHTTP方法,該方法将請求分發到不同的handler進行處理,每個handler處理一條請求路徑。有兩種注冊handler的方式:http.Handle和http.HandleFunc,兩種實作本質上是一緻的,前者需要明确寫出ServeHTTP方法的實作,後者由内置方法實作(見下文)。
Handler的接口定義如下:
http.HandleFunc的第二個參數被定義為HandlerFunc,實作了Handler接口。
當http.ListenAndServe的第二個參數為nil,則使用http.Handle和http.HandleFunc方法注冊的handler,預設儲存在http.DefaultServeMux.m中(注冊方法為ServeMux.Handle/ServeMux.HandleFunc)。當http server接收到一個request時,會在serverHandler.ServeHTTP中調用DefaultServeMux.ServeHTTP來處理接收到的request,分為兩步:
調用ServeMux.Handler函數,在ServeMux.m中根據pattern周遊查合适的handler
調用handler的ServeHTTP方法
serverHandler.ServeHTTP的源碼如下:
DefaultServeMux的結構體定義如下:
預設的handler的ServeHTTP方法實作如下,主要實作查找handler并處理請求
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=utf-8
< Location: /test/
< Date: Fri, 06 Dec 2019 03:35:59 GMT
< Content-Length: 41
<
<a href="/test/">Moved Permanently</a>.
*/
通常使用http.HandleFunc注冊handler,使用DefaultServeMux的方法分發處理請求即可。也可以通過http.NewServeMux()建立一個自定義的serverHandler,并實作Serve HTTP方法。
http.server
調用下面函數進行監聽,主要建立監聽socket并接收該socket上的連接配接。通常調用如下接口即可:
一個Server結構體表示一個啟用監聽端口的真實服務
ListenAndServe在建立監聽socket後調用Serve等待連接配接
ListenAndServeTLS與ListenAndServe類似,隻是入參多了證書參數
ServeTLS函數中會調用tls.NewListener建立一個tls類型的監聽socket,後續會調用tls的Accetp函數接收用戶端連接配接
Serve主要實作如下。通過Accept與用戶端建立連接配接後,通過newConn函數初始化一個HTTP連接配接,該連接配接包含HTTP的描述(監聽位址,URL等)和一個TCP連接配接,然後處理來自客戶的HTTP請求。
Accept傳回的底層的連接配接結構如下
實作如上接口的有tcpsock的TCPConn以及unixsock的UnixConn,通常使用TCPConn
newConn生成的HTTP結構體如下,它表示一條基于TCP的HTTP連接配接,封裝了3個重要的資料結構:server表示HTTP server的"server";rwc表示底層連接配接結構體rwc net.Conn;r用于讀取http資料的connReader(從rwc讀取資料)。後續的request和response都基于該結構體
connReader中的conn就是上面表示http連接配接的結構體
在下面的server函數中處理請求并傳回響應
readRequest函數處理http請求
讀取HTTP請求,并将其結構化為http.Request
http.transport
參見詳解transport
NetPoll
參見詳解golang net之netpoll
參考:
https://golang.org/pkg/net/http/
https://lanre.wtf/blog/2017/07/24/roundtripper-go/
https://lanre.wtf/blog/2017/04/03/http-in-go/