所以我在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's mux
包,并为每个相关的URL路径注册预检“OPTIONS”处理程序。
r := mux.NewRouter()
r.HandleFunc("/someresource/item", AddResourceHandler).Methods("PUT")
r.HandleFunc("/someresource/item", PreflightAddResourceHandler).Methods("OPTIONS")
也许对这个问题的回答很简单:是的,这些是你的基本选择。但我认为可能会有一些我不知道的最佳实践。
答案 0 :(得分:27)
分离逻辑并重新使用您定义的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))
答案 1 :(得分:5)
我个人觉得为每个获得OPTIONS
请求的路径添加预检路由非常繁琐,所以我只需将处理程序添加到Gorilla处理的任何OPTIONS
方法中,如下所示:
router.Methods("OPTIONS").HandlerFunc(
func(w http.ResponseWriter, r *http.Request){
myHttpLib.OptionsForBrowserPreflight(w, r)
})
请注意,这应该在映射其他路由之前进行,因为如果例如,您有一个类似"/foo"
的路径,并且您首先注册该路径而不指定该路由的任何方法,那么一个OPTIONS请求到" / foo"将运行而不是你的预检代码,因为它是第一场比赛。
通过这种方式,您可以:(1)对所有预飞行只有一个路由注册,(2)有一个处理程序可以重复使用代码并在一个地方为OPTIONS请求应用逻辑/规则。
答案 2 :(得分:4)
这是一个适合我的片段:
results
答案 3 :(得分:3)
gorilla/handlers还有一个很好的CORS处理程序:cors.go
使用示例:
import (
"net/http"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/users", UserEndpoint)
r.HandleFunc("/projects", ProjectEndpoint)
// Apply the CORS middleware to our top-level router, with the defaults.
http.ListenAndServe(":8000", handlers.CORS()(r))
}
答案 4 :(得分:0)
好吧,我的Vue.js应用程序对我没有任何帮助,所以我做到了。
cors := cors.New(cors.Options{
AllowedOrigins: []string{"*"}, //viper.GetString("ORIGIN_ALLOWED")
AllowedHeaders: []string{"Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token", "Authorization"},
AllowedMethods: []string{"GET", "PATCH", "POST", "PUT", "OPTIONS", "DELETE"},
Debug: true,
AllowCredentials: true,
})
cors.Handler(corsMiddle())
func corsMiddle() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
if request.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
}
})
}