How to handle preflight CORS requests on a Go server

ivarg picture ivarg · Apr 9, 2014 · Viewed 27.8k times · Source

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 the same-origin policy kicks in, so here we are).

In this scenario, the user agent will, in some cases, send preflight OPTIONS requests to check if the actual request is safe to send.

My question is how to best deal with, and adequately respond to, these preflight requests in a Go context. The ways I have conceived don't feel very elegant, and I'm wondering if there's some other approach to this that I haven't thought of.

Using the standard net/http package, I can check the request method in the handler func, perhaps like this:

func AddResourceHandler(rw http.ResponseWriter, r *http.Request) {
  switch r.Method {
  case "OPTIONS":
    // handle preflight
  case "PUT":
    // respond to actual request
  }
}

I can also use Gorilla's mux package, and register a preflight "OPTIONS" handler for each relevant URL path.

r := mux.NewRouter()
r.HandleFunc("/someresource/item", AddResourceHandler).Methods("PUT")
r.HandleFunc("/someresource/item", PreflightAddResourceHandler).Methods("OPTIONS")

Maybe the response to this question is simply: Yup, those are your basic options. But I thought there might be some best practice around this that I'm unaware of.

Answer

photoionized picture photoionized · Apr 9, 2014

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