Как заставить работать обработчик golang Gorilla CORS

У меня довольно простая настройка, как описано в приведенном ниже коде. Но я не могу получить CORS работать. Я продолжаю получать эту ошибку:

XMLHttpRequest не может загрузить http://localhost:3000/signup. Ответ на запрос предварительной проверки не проходит проверку контроля доступа: в запрашиваемом ресурсе отсутствует заголовок "Access- Control-Allow-Origin". Источник ' http://localhost:8000/', следовательно, не имеет доступа. Ответ имел HTTP-код состояния 403.

Я уверен, что мне здесь не хватает чего-то простого.

Вот код, который у меня есть:

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
    "myApp/src/controllers"
)

func main() {
    ac := new(controllers.AccountController)

    router := mux.NewRouter()
    router.HandleFunc("/signup", ac.SignUp).Methods("POST")
    router.HandleFunc("/signin", ac.SignIn).Methods("POST")

    log.Fatal(http.ListenAndServe(":3000", handlers.CORS()(router)))
}

8 ответов

Решение

Пожалуйста, прочитайте ссылку, предложенную Маркусом, а также о том, что запускает предполетные запросы CORS.

Предполетные запросы: у вас может быть тип контента, например JSON, или какой-либо другой настраиваемый заголовок, который запускает предполетный запрос, который может не обрабатываться вашим сервером. Попробуйте добавить этот, если вы используете постоянно используемый AJAX в своем интерфейсе: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields

гориллы handlers.CORS() установит разумные значения по умолчанию, чтобы заставить работать с вами CORS; однако, вы можете (и, возможно, должны) взять на себя управление более функциональным способом.

Вот некоторый стартовый код:

headersOk := handlers.AllowedHeaders([]string{"X-Requested-With"})
originsOk := handlers.AllowedOrigins([]string{os.Getenv("ORIGIN_ALLOWED")})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})

// start server listen
// with error handling
log.Fatal(http.ListenAndServe(":" + os.Getenv("PORT"), handlers.CORS(originsOk, headersOk, methodsOk)(router)))

Вы можете получить более подробную информацию здесь: "Нет заголовка" Access-Control-Allow-Origin "на запрошенном ресурсе" об этой проблеме.

Также попробуйте этот обработчик: Go Cors Handler, который должен решить вашу проблему. Я считаю, что это намного чище и легко решить проблему.

package main

import (
    "log"
    "net/http"
    "github.com/rs/cors"
    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
    "myApp/src/controllers"
)

func main() {
    ac := new(controllers.AccountController)

    router := mux.NewRouter()
    router.HandleFunc("/signup", ac.SignUp).Methods("POST")
    router.HandleFunc("/signin", ac.SignIn).Methods("POST")

    c := cors.New(cors.Options{
    AllowedOrigins: []string{"http://localhost:8000"},
    AllowCredentials: true,
    })

    handler := c.Handler(router)

    log.Fatal(http.ListenAndServe(":3000", handler )
}

Вы должны создать CORSOption объект. Например, чтобы разрешить любое происхождение, используйте этот код:

corsObj:=handlers.AllowedOrigins([]string{"*"})

Затем вы передаете этот объект вашему handle.CORS функция:

log.Fatal(http.ListenAndServe(":3000", handlers.CORS(corsObj)(router)))

Для тестирования вы можете использовать CURL:

curl -H "Origin: http://example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: X-Requested-With" \
-X OPTIONS --verbose http://127.0.0.1:3000

Когда это работает, вы должны увидеть эти заголовки:

> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: X-Requested-With

Финальный код здесь: https://play.golang.org/p/AOrlJsWhvf

Больше информации:

После объявления объекта мультиплексора добавьте accessControlMiddleware в качестве промежуточного программного обеспечения к объявленному объекту.

func main(){
  ac := new(controllers.AccountController)

    router := mux.NewRouter()
    router.Use(accessControlMiddleware)
    router.HandleFunc("/signup", ac.SignUp).Methods("POST")
    router.HandleFunc("/signin", ac.SignIn).Methods("POST")
    http.ListenAndServe(":3000", corsOpts.Handler(router))
}

// access control and  CORS middleware
func accessControlMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Access-Control-Allow-Origin", "*")
            w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS,PUT")
            w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type")

                if r.Method == "OPTIONS" {
                    return
                }

                next.ServeHTTP(w, r)
            })
        }

Я понимаю, что это старая проблема, но, тем не менее, мне потребовалось 30 минут, чтобы исправить это.

handler = handlers.CORS(
    // handlers.AllowedMethods([]string{"GET", "POST", "PUT"}),
    handlers.AllowedHeaders([]string{"Accept", "Accept-Language", "Content-Type", "Content-Language", "Origin"}),
    // handlers.AllowedOrigins([]string{"*"}),
)(handler)

На заметку:

  • AllowedMethods НЕ нужно явно включать OPTIONS, это часть обработчика CORS
  • Необходимо явно указать AllowedHeaders, *не является допустимым подстановочным знаком. Типичные библиотеки ajax отправятContent-Type при запросе чего-то вроде application/json, так что добавьте и это.
  • * по умолчанию для AllowedOrigin
package main

import (
    "log"
    "net/http"

    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
    "myApp/src/controllers"
       "github.com/rs/cors"
)

func main() {

     ac := new(controllers.AccountController)

    router := mux.NewRouter()
    router.HandleFunc("/signup", ac.SignUp).Methods("POST")
    router.HandleFunc("/signin", ac.SignIn).Methods("POST")
//cors optionsGoes Below
corsOpts := cors.New(cors.Options{
    AllowedOrigins: []string{"http://localhost:8100"}, //you service is available and allowed for this base url 
    AllowedMethods: []string{
        http.MethodGet,//http methods for your app
        http.MethodPost,
        http.MethodPut,
        http.MethodPatch,
        http.MethodDelete,
        http.MethodOptions,
        http.MethodHead,
    },

    AllowedHeaders: []string{
        "*",//or you can your header key values which you are using in your application

    },
})

    http.ListenAndServe(":3000", corsOpts.Handler(router))
}

Основываясь на ответе jeremiah.trein.

Фильтры CORS устанавливаются на стороне сервера. Запрос может работать с Postman и завершаться ошибкой с браузером, потому что Postman не отправляет предпечатный запрос, в отличие от браузера.

Установка фильтров CORS позволит вам настроить источники, методы и заголовки, которые должна принимать серверная часть.

Кроме того, если ваш браузер отправляет запросы POST или PUT, которые содержат полезные данные json (что вполне разумно), вам необходимо добавить 'Content-Type' к разрешенным заголовкам.

Наконец handlers.CORS()(router) не только работает с http.ListenAndServe функция, но также с http.Handle().

Фрагмент кода может выглядеть так:

router := mux.NewRouter()

// do all your routes declaration

headersOK := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOK := handlers.AllowedOrigins([]string{"*"})
methodsOK := handlers.AllowedMethods([]string{"GET", "POST", "OPTIONS", "DELETE", "PUT"})

http.Handle("/", handlers.CombinedLoggingHandler(os.Stderr, handlers.CORS(headersOK, originsOK, methodsOK)(router)))

Стоит отметить, что я успешно использовал этот фрагмент кода в стандартном AppEngine Google Cloud Platform (и я считаю, что он также будет работать в Flex AppEngine).

Вышеупомянутый пакет github.com/rs/cors предоставляет конструктор

      AllowAll() *Cors

что

... создайте новый обработчик Cors с разрешительной конфигурацией, разрешающей все источники со всеми стандартными методами с любым заголовком и учетными данными.

Другие вопросы по тегам