Как обрабатывать запросы preflight CORS на сервере Go
поэтому я пишу этот RESTful backend в Go, который будет вызываться с помощью межсайтовых HTTP-запросов, т. е. из контента, обслуживаемого другим сайтом (на самом деле, просто другой порт, но политика того же происхождения, так что мы здесь).
в этом случае агент пользователя будет в некоторых случаях отправлять запросы параметров предполетной проверки, чтобы проверить, является ли фактический запрос безопасным для отправки.
мой вопрос заключается в том, как лучше всего справиться и адекватно ответить на эти предполетные запросы в 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
}
}
Я также могу использовать гориллы mux
package и зарегистрируйте обработчик "OPTIONS" для каждого соответствующего URL-адреса.
r := mux.NewRouter()
r.HandleFunc("/someresource/item", AddResourceHandler).Methods("PUT")
r.HandleFunc("/someresource/item", PreflightAddResourceHandler).Methods("OPTIONS")
возможно, ответ на этот вопрос просто: Да, это основные варианты. но я думал, что может быть какая-то лучшая практика вокруг этого, о которой я не знаю.
5 ответов
один простой способ отделить вашу логику и повторно использовать обработчик 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))
эта библиотека выглядит многообещающе:
Go CORS handler
CORS-обработчик net / http, реализующий совместное использование ресурсов Cross Origin Спецификация W3 в Golang.
Я лично считаю утомительным добавлять предполетные маршруты для каждого пути, который получит OPTIONS
запрос, поэтому вместо этого я просто добавляю свой обработчик в любой OPTIONS
метод, который горилла обрабатывает следующим образом:
router.Methods("OPTIONS").HandlerFunc(
func(w http.ResponseWriter, r *http.Request){
myHttpLib.OptionsForBrowserPreflight(w, r)
})
обратите внимание, что это должно произойти перед отображением других маршрутов, потому что если, , у вас есть путь как "/foo"
и вы регистрируете это сначала без указания каких-либо методов для этого маршрута, а затем вместо вашего предполетный код, потому что его первое совпадение.
таким образом, вы можете: (1) иметь только одну регистрацию маршрутизации для всех предварительных рейсов и (2) иметь один обработчик для повторного использования кода и применения логики/правил в одном месте для запросов опций.
горилла/обработчики также имеет хороший обработчик 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))
}
вот фрагмент, который работал для меня:
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")
}