概述
调试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的代码,该段代码的实现十分的简单,首先查看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)
- 用来检查服务器的性能
网友评论