這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
原文:Golang Http Handlers as Middleware
譯者:youngsterxyf
大多數現代Web組件棧允許通過棧式/組件式中介軟體“過濾”請求,這樣就能乾淨地從web應用中分離出橫切關注點(譯註:面向方面程式設計中的概念?)。本周我嘗試在Go語言的http.FileServer
中植入鉤子,發現實現起來十分簡便,讓我非常驚訝。
讓我們從一個基本的檔案伺服器開始說起:
func main() { http.ListenAndServe(":8080", http.FileServer(http.Dir("/tmp")))}
這段程式會在連接埠8080上開啟一個本地檔案伺服器。那麼我們該如何在這其中植入鉤子從而能夠在檔案請求處理之前執行一些代碼?來看一下http.ListenAndServe
的方法簽名:
func ListenAndServe(addr string, handler Handler) error
看起來http.FileServer
返回了一個Handler
---給定一個根目錄就能知道如何處理檔案請求。那我們來看看Handler
介面:
type Handler interface { ServeHTTP(ResponseWriter, *Request)}
根據Go語言的介面原理,任何對象只要實現了ServeHTTP
就是一個Handler
。那麼似乎我們需要做的事情就是構造一個自己的Handler
---封裝http.FileServer
的處理流程。Go語言的net/http標準庫模組內建了一個協助函數http.HandlerFunc
,用於將普通函數轉變為請求處理函數(handler):
type HandlerFunc func(ResponseWriter, *Request)
那麼我們這樣封裝http.FileServer
就可以了:
func OurLoggingHandler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request)) { fmt.Println(*r.URL) h.ServeHTTP(w ,r) })}func main() { fileHandler := http.FileServer(http.Dir("/tmp")) wrappedHandler := OurLoggingHandler(fileHandler) http.ListenAndServe(":8080", wrappedHandler)}
Go語言的net/http標準庫模組有很多內建的處理函數,如TimeoutHandler和RedirectHandler,可以相同的方式混合匹配使用。
譯者推薦閱讀