简体   繁体   English

带有 golang 后端的 CORS 请求不起作用

[英]CORS request with golang backend doesn't works

I'm facing some issue with my implementation.我的实施面临一些问题。 I have a backend written in Golang and the UI (in Angular2) which are on the same server.我有一个用 Golang 编写的后端和位于同一服务器上的 UI(在 Angular2 中)。

I've tried to set the CORS handling in my backend but it still doesn't work and I'm not getting why.我试图在我的后端设置 CORS 处理,但它仍然不起作用,我不明白为什么。

Here's my code:这是我的代码:

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/mux"
    "github.com/rs/cors"
)

var router *mux.Router

func main() {
    router = mux.NewRouter()

    HandleFuncEx("/authentication", handleAuthentication)
    HandleFuncEx("/callA", handleCallA)
    HandleFuncEx("/callB", handleCallB)
    HandleFuncEx("/callC", handleCallC)

    handler := cors.New(cors.Options{
        AllowedOrigins: []string{"*"},
        AllowedMethods: []string{"GET", "POST", "PATCH"},
        AllowedHeaders: []string{"a_custom_header", "content_type"},
    }).Handler(router)
    http.ListenAndServe(":8000", handler)

}

func HandleFuncEx(pattern string, handler func(http.ResponseWriter, *http.Request)) {
    log.Println("handled function", pattern)
    router.HandleFunc(pattern, handler)
}

The authentication pattern works correctly (is the first called by the UI) all the others calls fails the preflight request.身份验证模式正常工作(是 UI 的第一个调用),所有其他调用都未通过预检请求。 Why is it happening?为什么会发生?

Thanks everybody for the help!感谢大家的帮助!

EDIT:编辑:

This is an example of a non-working response Headers:这是非工作响应标头的示例:

HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Date: Fri, 07 Apr 2017 08:33:12 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

And these are request's headers:这些是请求的标头:

OPTIONS /users HTTP/1.1
Host: /* Removed by my company policy */
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: /* Removed by my company policy */
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Access-Control-Request-Headers: access_token
Accept: */*
Referer: /* Removed by my company policy */
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,it;q=0.4,la;q=0.2

As Adrian pointed out, you need to add the OPTIONS Method to the AllowedMethods array.正如Adrian指出的那样,您需要将OPTIONS方法添加到AllowedMethods数组中。

Please also consider to add Accept , Accept-Language and Content-Type to the AllowedHeaders as good practice.还请考虑将AcceptAccept-LanguageContent-TypeAllowedHeaders作为良好做法。

If you don't want to use the github.com/rs/cors package, you can write a simple CORS decorator middleware on your own like this:如果您不想使用github.com/rs/cors包,您可以像这样自己编写一个简单的 CORS 装饰器中间件:

CORS decorator CORS 装饰器

import (
    "net/http"

    "github.com/gorilla/mux"
)

// CORSRouterDecorator applies CORS headers to a mux.Router
type CORSRouterDecorator struct {
    R *mux.Router
}

// ServeHTTP wraps the HTTP server enabling CORS headers.
// For more info about CORS, visit https://www.w3.org/TR/cors/
func (c *CORSRouterDecorator) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    if origin := req.Header.Get("Origin"); origin != "" {
        rw.Header().Set("Access-Control-Allow-Origin", origin)
        rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        rw.Header().Set("Access-Control-Allow-Headers", "Accept, Accept-Language, Content-Type, YourOwnHeader")
    }
    // Stop here if its Preflighted OPTIONS request
    if req.Method == "OPTIONS" {
        return
    }

    c.R.ServeHTTP(rw, req)
}

HTTP server HTTP服务器

r := mux.NewRouter()
r.Handle("/authentication", handleAuthentication)

http.Handle("/", &CORSRouterDecorator{r})

et voilà.等等。

I use Negroni as middleware and this code:我使用 Negroni 作为中间件,代码如下:

func main() {

    c := cors.New(cors.Options{
        AllowedOrigins: []string{"*"},
        AllowedMethods: []string{"POST", "GET", "OPTIONS", "PUT", "DELETE"},
        AllowedHeaders: []string{"Accept", "content-type", "Content-Length", "Accept-Encoding", "X-CSRF-Token", "Authorization"},
    })

    router := mux.NewRouter()
    router = routers.SetAuthRoute(router)

    apiRoutes := routers.InitRoutes()

    router.PathPrefix("/api").Handler(negroni.New(
        negroni.HandlerFunc(controllers.ValidateTokenMiddleware),
        negroni.Wrap(apiRoutes),
    ))

    server := negroni.Classic()
    server.Use(c)
    server.UseHandler(router)
    server.Run("0.0.0.0:" + os.Getenv("PORT"))
}

Similar to the other two responses, but I my case my project is hosted on cloud9 so I had a couple of tweaks to do.与其他两个响应类似,但我的案例是我的项目托管在 cloud9 上,所以我需要做一些调整。

This is the code i added:这是我添加的代码:

    cor := cors.New(cors.Options{
        AllowedOrigins:   []string{"https://*.c9users.io", "http://myapp.c9users.io:8080", "https://*.c9.io"},
        AllowedMethods:   []string{"POST", "GET", "OPTIONS", "PUT"},
        AllowedHeaders:   []string{"Accept", "Accept-Language", "Content-Type"},
        AllowCredentials: true,
        Debug:            true,
    });

I had to add the extra http origin as Safari makes the initial options request using http instead of https.我不得不添加额外的 http 源,因为 Safari 使用 http 而不是 https 发出初始选项请求。

Sorted.排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM