所以我在Go中编写这个RESTful后端,它将通过跨站点HTTP请求调用,即来自另一个站点服务的内容(实际上,只是另一个端口,但同源策略启动,所以我们这里) .
在这种情况下,用户代理在某些情况下会发送预检OPTIONS请求,以检查实际请求是否可以安全发送.
我的问题是如何在Go环境中最好地处理和充分响应这些预检请求.我设想的方式并不是很优雅,我想知道是否有其他方法可以解决这个问题.
使用标准net/http
包,我可以检查处理程序func中的请求方法,也许是这样的:
func AddResourceHandler(rw http.ResponseWriter, r *http.Request) { switch r.Method { case "OPTIONS": // handle preflight case "PUT": // respond to actual request } }
我也可以使用Gorilla的 mux
包,并为每个相关的URL路径注册预检"OPTIONS"处理程序.
r := mux.NewRouter() r.HandleFunc("/someresource/item", AddResourceHandler).Methods("PUT") r.HandleFunc("/someresource/item", PreflightAddResourceHandler).Methods("OPTIONS")
也许对这个问题的回答很简单:是的,这些是你的基本选择.但我认为可能有一些最好的做法,我不知道.
分离逻辑并重新使用您定义的CORS处理程序的一种简单方法是包装REST处理程序.例如,如果你使用net/http和Handle
方法,你总是可以这样做:
func corsHandler(h http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if (r.Method == "OPTIONS") { //handle preflight in here } else { h.ServeHTTP(w,r) } } }
你可以像这样包装:
http.Handle("/endpoint/", corsHandler(restHandler))
我个人觉得为每个获取OPTIONS
请求的路径添加预检路由很繁琐,所以我只需将处理程序添加到OPTIONS
Gorilla处理的任何方法,如下所示:
router.Methods("OPTIONS").HandlerFunc( func(w http.ResponseWriter, r *http.Request){ myHttpLib.OptionsForBrowserPreflight(w, r) })
但是请注意,这应该在映射其他路由之前进行,因为例如,如果您有一个类似的路径"/foo"
并且首先注册该路径而不指定该路由的任何方法,那么对"/ foo"的OPTIONS请求将运行而不是您的预检代码,因为它的第一个匹配.
通过这种方式,您可以:(1)对所有预飞行只有一个路由注册,以及(2)有一个处理程序可以重用代码并在一个地方为OPTIONS请求应用逻辑/规则.