綜述
調(diào)試樣例為examples\restful-no-cache-filter.go
,在該例子主要是對hello world樣例的擴(kuò)展医瘫,主要在hello world中添加Filter亚隙,用來消除http訪問的cache何乎,代碼如下饵较。
func main() {
ws := new(restful.WebService)
ws.Filter(restful.NoBrowserCacheFilter)
ws.Route(ws.GET("/hello").To(hello))
restful.Add(ws)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func hello(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "world")
}
Filter添加流程
ws.Filter(restful.NoBrowserCacheFilter)
從字面意思上理解就是講一個(gè)NoBrowserCacheFilter
對象添加到filter
中竹观,NoBrowserCacheFilter
是定義的FilterFunction
函數(shù)镐捧。
// FilterFunction definitions must call ProcessFilter on the FilterChain to pass on the control and eventually call the RouteFunction
type FilterFunction func(*Request, *Response, *FilterChain)
// NoBrowserCacheFilter is a filter function to set HTTP headers that disable browser caching
// See examples/restful-no-cache-filter.go for usage
func NoBrowserCacheFilter(req *Request, resp *Response, chain *FilterChain) {
resp.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
resp.Header().Set("Pragma", "no-cache") // HTTP 1.0.
resp.Header().Set("Expires", "0") // Proxies.
chain.ProcessFilter(req, resp)
}
在ws結(jié)構(gòu)體中存有記錄Filter相關(guān)數(shù)據(jù)的字段潜索,對應(yīng)的添加接口為,并將FilterFunction:NoBrowserCacheFilter
添加到type WebService struct { filters []FilterFunction }
中進(jìn)行維護(hù),ws的啟動(dòng)流程同example/hello-world.go
的流程相同懂酱。
func (w *WebService) Filter(filter FilterFunction) *WebService {
w.filters = append(w.filters, filter)
return w
}
Filter函數(shù)的執(zhí)行
在http請求訪問時(shí)竹习,restful調(diào)用dispatch進(jìn)行req的分發(fā),在完成route select之后列牺,執(zhí)行綁定的hello函數(shù)前整陌,需要對用戶定的的Filter進(jìn)行先行判定, 并將用戶定義的Filter全部統(tǒng)計(jì)到allFilters中,并初始化FilterChain瞎领,在restful中Filter的規(guī)則是可以被覆蓋掉的泌辫,按照優(yōu)先級container filter < webservices < route執(zhí)行。
func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
if len(c.containerFilters)+len(webService.filters)+len(route.Filters) > 0 {
// compose filter chain
allFilters := []FilterFunction{}
allFilters = append(allFilters, c.containerFilters...)
allFilters = append(allFilters, webService.filters...)
allFilters = append(allFilters, route.Filters...)
chain := FilterChain{Filters: allFilters, Target: func(req *Request, resp *Response) {
// handle request by route after passing all filters
route.Function(wrappedRequest, wrappedResponse)
}}
chain.ProcessFilter(wrappedRequest, wrappedResponse)
} else {// example hello world在這里執(zhí)行執(zhí)行綁定函數(shù)
// no filters, handle request by route
route.Function(wrappedRequest, wrappedResponse)
}
}
Filter Chain中實(shí)際上是對Filter規(guī)則和目標(biāo)function的進(jìn)一步包裝九默,之所以叫做chain是因?yàn)閷liter的執(zhí)行是通過遞歸調(diào)用的方式震放,并有Index控制Filter的遞歸層數(shù),代碼如下:
// FilterChain is a request scoped object to process one or more filters before calling the target RouteFunction.
type FilterChain struct {
Filters []FilterFunction // ordered list of FilterFunction
Index int // index into filters that is currently in progress
Target RouteFunction // function to call after passing all filters
}
其中Filter字段中記錄了所有的Filter規(guī)則驼修,Targe綁定了玩家定義的需要執(zhí)行的函數(shù)殿遂, 后面通過調(diào)用定義在Filter中的ProcessFilter函數(shù)執(zhí)行對應(yīng)的Filters及user function: hello。
// ProcessFilter passes the request,response pair through the next of Filters.
// Each filter can decide to proceed to the next Filter or handle the Response itself.
func (f *FilterChain) ProcessFilter(request *Request, response *Response) {
if f.Index < len(f.Filters) {
f.Index++
f.Filters[f.Index-1](request, response, f)
} else {
f.Target(request, response)
}
}
用戶自定義filter
既然restful提供了Filter的通用接口乙各,并提供NoBrowserCacheFilter樣例墨礁,那么用戶也可以自定義響應(yīng)的Filter接口,在該小結(jié)中耳峦,將仿照NoBrowserCacheFilter的實(shí)現(xiàn)方式在package main中自定義用戶的Filter函數(shù)饵溅,改變用戶訪問resp的header中的字段,代碼如下:
func main() {
ws := new(restful.WebService)
ws.Filter(restful.NoBrowserCacheFilter)
// 將自定義Filter添加到ws Filter中
ws.Filter(UserCustomFilter)
ws.Route(ws.GET("/hello").To(hello))
restful.Add(ws)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func UserCustomFilter(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
//創(chuàng)建新字段
resp.Header().Set("custom", "test") // HTTP 1.1.
//覆蓋掉NoBrowserCacheFilter中的pargma字段
resp.Header().Set("Pragma", "test") // HTTP 1.0.
//遞歸調(diào)用下一個(gè)pross Filter妇萄,取名為chain的原因
chain.ProcessFilter(req, resp)
}
http訪問后返回的http header如下:其中用戶自定義的Filter覆蓋掉了NoBrowserCacheFilter中的pargma字段蜕企,并新添加custom字段。
cache-control → no-cache, no-store, must-revalidate
custom → test
date →Tue, 21 Aug 2018 08:40:14 GMT
expires → 0
pragma → test