go - headers - options get
Cómo manejar las solicitudes CORL de verificación previa en un servidor Go (5)
Así que estoy escribiendo este backend RESTful en Go, que se llamará con solicitudes HTTP entre sitios, es decir, desde el contenido servido por otro sitio (en realidad, solo otro puerto, pero la política del mismo origen se activa, así que aquí estamos) .
En este escenario, el agente de usuario, en algunos casos, enviará solicitudes de OPCIONES de verificación previa para verificar si la solicitud real es segura de enviar.
Mi pregunta es cómo tratar mejor y responder adecuadamente a estas solicitudes de verificación previa en un contexto Go. Las formas que he concebido no se sienten muy elegantes, y me pregunto si hay algún otro enfoque al respecto que no haya pensado.
Utilizando el paquete estándar net/http
, puedo verificar el método de solicitud en el controlador func, quizás así:
func AddResourceHandler(rw http.ResponseWriter, r *http.Request) {
switch r.Method {
case "OPTIONS":
// handle preflight
case "PUT":
// respond to actual request
}
}
También puedo usar Gorilla''s paquete mux
Gorilla''s y registrar un controlador "OPTIONS" de verificación previa para cada ruta de URL relevante.
r := mux.NewRouter()
r.HandleFunc("/someresource/item", AddResourceHandler).Methods("PUT")
r.HandleFunc("/someresource/item", PreflightAddResourceHandler).Methods("OPTIONS")
Tal vez la respuesta a esta pregunta es simple: Sí, esas son tus opciones básicas. Pero pensé que podría haber algunas mejores prácticas al respecto que desconozco.
Aquí hay un fragmento que funcionó para mí:
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")
}
Esta biblioteca parece prometedora:
Ir al controlador CORS
CORS es un controlador de red / http que implementa la especificación Cross Origin Resource Sharing W3 en Golang.
Personalmente, me resulta tedioso agregar rutas de verificación previa para cada ruta que recibirá una solicitud de OPTIONS
, por lo que simplemente agrego mi controlador a cualquier método de OPTIONS
que maneje Gorilla de la siguiente manera:
router.Methods("OPTIONS").HandlerFunc(
func(w http.ResponseWriter, r *http.Request){
myHttpLib.OptionsForBrowserPreflight(w, r)
})
Sin embargo, tenga en cuenta que esto debe venir antes de mapear otras rutas porque si, por ejemplo , tiene una ruta como "/foo"
y la registra primero sin especificar ningún método para esa ruta, se ejecutará una solicitud de OPCIONES a "/ foo" en lugar de su código de verificación previa porque es la primera coincidencia.
De esta manera usted puede: (1) tener solo un registro de enrutamiento para todos los vuelos previos, y (2) tener un manejador para reutilizar el código y aplicar la lógica / reglas en un solo lugar para las solicitudes de OPCIONES.
Una forma simple de separar tu lógica y reutilizar el controlador CORS que defines sería envolver tu controlador REST. Por ejemplo, si usa net / http y el método Handle
, siempre puede hacer algo como:
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)
}
}
}
Puedes envolver así:
http.Handle("/endpoint/", corsHandler(restHandler))
gorilla/handlers también tiene un buen manejador CORS: cors.go
Ejemplo de uso:
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))
}