How to handle preflight CORS requests on a Go server

前端 未结 5 882
时光说笑
时光说笑 2020-12-09 01:48

So I\'m writing this RESTful backend in Go, which will be called with cross-site HTTP requests, i.e. from content served by another site (actually, just another port, but th

相关标签:
5条回答
  • 2020-12-09 01:55

    Well, nothing worked from me from my Vue.js application so I did this.

    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)
            }
        })
    }
    
    0 讨论(0)
  • 2020-12-09 01:58

    One simple way to separate out your logic and re-use the CORS handler you define would be to wrap your REST handler. For example, if you're using net/http and the Handle method you could always do something like:

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

    You can wrap like this:

    http.Handle("/endpoint/", corsHandler(restHandler))
    
    0 讨论(0)
  • 2020-12-09 02:03

    gorilla/handlers also has a nice CORS handler: cors.go

    Example usage:

    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))
    }
    
    0 讨论(0)
  • 2020-12-09 02:06

    I personally find it tedious to add preflight routes for every path that will get an OPTIONS request, so instead I simply add my handler to any OPTIONS method that the request multiplexer (Gorilla in this case) handles as follows:

    router.Methods("OPTIONS").HandlerFunc(
        func(w http.ResponseWriter, r *http.Request){
        myHttpLib.OptionsForBrowserPreflight(w, r)
    })
    

    Note though, that this should come before mapping other routes because if, for example, you have a path like "/foo" and you register that first without specifying any methods for that route, then an OPTIONS request to "/foo" would run instead of your pre-flight code because its the first match.

    This way you can: (1) have just one routing registration for all pre-flights, and (2) have one handler to reuse code and apply logic/rules in a single place for OPTIONS requests.

    0 讨论(0)
  • 2020-12-09 02:10

    Here's a snippet that worked for me:

    addCorsHeader(res)
    if req.Method == "OPTIONS" {
        res.WriteHeader(http.StatusOK)
        return
    } else {
        h.APIHandler.ServeHTTP(res, req)
    }
    
    
    func addCorsHeader(res http.ResponseWriter) {
        headers := res.Header()
        headers.Add("Access-Control-Allow-Origin", "*")
        headers.Add("Vary", "Origin")
        headers.Add("Vary", "Access-Control-Request-Method")
        headers.Add("Vary", "Access-Control-Request-Headers")
        headers.Add("Access-Control-Allow-Headers", "Content-Type, Origin, Accept, token")
        headers.Add("Access-Control-Allow-Methods", "GET, POST,OPTIONS")
    }
    
    0 讨论(0)
提交回复
热议问题