3 回答

TA貢獻(xiàn)1852條經(jīng)驗(yàn) 獲得超1個(gè)贊
中間件鏈
這個(gè)問(wèn)題的一個(gè)常見(jiàn)解決方案是所謂的中間件鏈。有幾個(gè)庫(kù)提供此功能,例如negroni。
這是一種延續(xù)傳遞風(fēng)格的形式,您可以像這樣編寫(xiě)中間件函數(shù)(取自 negroni 的自述文件):
func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
// do some stuff before
next(rw, r)
// do some stuff after
}
然后 negroni 為您提供一個(gè) HTTP 處理程序,以正確的順序調(diào)用您的中間件。
我們可以以稍微不同的方式實(shí)現(xiàn)這個(gè)解決方案,而不是一種不太神奇但功能更多的方法(如在函數(shù)式編程中)。定義處理程序組合子如下:
func NewFooHandler(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// do some stuff before
next(r,w)
// do some stuff after
}
}
然后將您的鏈定義為一個(gè)組合:
h := NewFooHandler(NewBarHandler(NewBazHandler(Sink)))
現(xiàn)在h是http.HandlerFuncfoo,然后是 bar,然后是 baz。Sink只是一個(gè)空的最后一個(gè)處理程序,什么都不做(“完成”鏈。)
將此解決方案應(yīng)用于您的問(wèn)題
定義一個(gè)處理程序組合子:
func NewResponseLoggingHandler(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// switch out response writer for a recorder
// for all subsequent handlers
c := httptest.NewRecorder()
next(c, r)
// copy everything from response recorder
// to actual response writer
for k, v := range c.HeaderMap {
w.Header()[k] = v
}
w.WriteHeader(c.Code)
c.Body.WriteTo(w)
}
}
現(xiàn)在問(wèn)題歸結(jié)為處理程序管理。您可能希望將此處理程序應(yīng)用于某個(gè)類(lèi)別中的所有鏈。為此,您可以再次使用組合器(這在某種程度上相當(dāng)于 negroni 的Classic()方法):
func NewDefaultHandler(next http.HandlerFunc) http.HandlerFunc {
return NewResponseLoggingHandler(NewOtherStuffHandler(next))
}
在此之后,每當(dāng)您啟動(dòng)這樣的鏈時(shí):
h := NewDefaultHandler(...)
它將自動(dòng)包含響應(yīng)日志記錄和您在NewDefaultHandler.
- 3 回答
- 0 關(guān)注
- 234 瀏覽
添加回答
舉報(bào)