概述
調(diào)試go-restful\examples中的restful-options-filter,在該段代碼中主要介紹了處理http option請求的流程宝冕,在改短代碼中采用了之前通用的container初始化及注冊流程遍搞,只是在fliter中添加了對應的OPTIONSFilter。
type UserResource struct{}
func (u UserResource) RegisterTo(container *restful.Container) {
ws := new(restful.WebService)
ws.
Path("/users").
Consumes("*/*").
Produces("*/*")
ws.Route(ws.GET("/{user-id}").To(u.nop))
ws.Route(ws.POST("").To(u.nop))
ws.Route(ws.PUT("/{user-id}").To(u.nop))
ws.Route(ws.DELETE("/{user-id}").To(u.nop))
container.Add(ws)
}
func (u UserResource) nop(request *restful.Request, response *restful.Response) {
io.WriteString(response.ResponseWriter, "this would be a normal response")
}
func main() {
wsContainer := restful.NewContainer()
u := UserResource{}
u.RegisterTo(wsContainer)
// Add container filter to respond to OPTIONS
wsContainer.Filter(wsContainer.OPTIONSFilter)
// For use on the default container, you can write
// restful.Filter(restful.OPTIONSFilter())
log.Print("start listening on localhost:8080")
server := &http.Server{Addr: ":8080", Handler: wsContainer}
log.Fatal(server.ListenAndServe())
OPTIONSFilter流程
先看下OPTIONSFilter的代碼判莉,該段代碼的實現(xiàn)十分的簡單小作,首先查看req方法是否是option方法,并針對option方法定制了resp直接進行返回。
func (c *Container) OPTIONSFilter(req *Request, resp *Response, chain *FilterChain) {
if "OPTIONS" != req.Request.Method {
chain.ProcessFilter(req, resp)
return
}
archs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
methods := strings.Join(c.computeAllowedMethods(req), ",")
origin := req.Request.Header.Get(HEADER_Origin)
resp.AddHeader(HEADER_Allow, methods)
resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
resp.AddHeader(HEADER_AccessControlAllowHeaders, archs)
resp.AddHeader(HEADER_AccessControlAllowMethods, methods)
}
由于之前并不了解option方法悬嗓,因此通過查閱得知option方法主要用于有兩個:
- 獲取服務器支持的HTTP請求方法
strings.Join(c.computeAllowedMethods(req), ",") resp.AddHeader(HEADER_Allow, methods)
- 用來檢查服務器的性能