如何在Go服务器上处理预检CORS请求

时间:2014-04-09 19:20:52

标签: go cors preflight

所以我在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")

也许对这个问题的回答很简单:是的,这些是你的基本选择。但我认为可能会有一些我不知道的最佳实践。

5 个答案:

答案 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)
        }
    })
}