44

我在这里有相当简单的设置,如下面的代码中所述。但我无法开始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)))
}
4

8 回答 8

65

请阅读 Markus 建议的链接,以及触发 CORS 飞行前请求的内容。

飞行前请求:您可能有 JSON 之类的内容类型,或其他触发飞行前请求的自定义标头,您的服务器可能无法处理这些请求。如果您在前端使用常见的 AJAX,请尝试添加这个:https ://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With

Gorillahandlers.CORS()将设置合理的默认值,让 CORS 的基础知识为您工作;但是,您可以(也许应该)以更实用的方式进行控制。

这是一些入门代码:

// Where ORIGIN_ALLOWED is like `scheme://dns[:port]`, or `*` (insecure)
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)))
于 2016-12-06T03:34:53.873 回答
33

您可以在此处获取更多详细信息:当我的 JavaScript 代码出现错误时,为什么 Postman 没有收到“请求的资源上不存在‘访问控制允许来源’标头”错误?关于这个问题。

也试试这个处理程序: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)
}
于 2017-07-06T21:57:12.207 回答
20

您应该创建一个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

更多信息:

于 2016-12-06T03:38:33.080 回答
4

声明mux对象后,将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)
            })
        }
于 2019-12-24T16:23:29.887 回答
4

基于 jeremiah.trein 的回答。

CORS 过滤器设置在服务器端。请求可能与 Postman 一起使用,而在浏览器中失败,因为 Postman 不发送预检请求,而浏览器发送。

设置 CORS 过滤器将允许您配置后端应接受的来源、方法和标头。

此外,如果您的浏览器发出包含 json 有效负载的 POST 或 PUT 请求(这是非常合理的),您需要添加'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)))

值得一提的是,我已经在 Google Cloud Platform Standard AppEngine 中成功使用了这段代码(我相信它也可以在 Flex AppEngine 中使用)。

于 2020-03-02T21:53:24.353 回答
4
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))
}
于 2018-10-16T19:26:15.040 回答
4

我意识到这是一个老问题,但我花了 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 的默认值
于 2019-12-31T10:33:40.730 回答
0

上述包github.com/rs/cors提供了一个构造函数

AllowAll() *Cors

...创建一个具有许可配置的新 Cors 处理程序,允许使用所有标准方法以及任何标头和凭据的所有来源。

于 2021-12-22T09:38:15.900 回答