在使用 kami 创建的 golang 服务器中使用 CORS。

huangapple go评论116阅读模式
英文:

Using CORS in golang server made with kami

问题

你好,我正在尝试从运行在localhost:8000上的Golang API访问一个GET请求,该请求来自运行在localhost:3000上的ReactJS Web应用程序。但是每当我尝试这样做时,我都会收到以下错误信息:

Fetch API无法加载http://localhost:8000/api/v1/systems。
请求的资源上没有'Access-Control-Allow-Origin'头。
因此,不允许来自'http://localhost:3000'的访问。响应的HTTP状态码为401。
如果不透明的响应满足您的需求,请将请求的模式设置为'no-cors'以禁用CORS获取资源。

这是我的Go服务器代码片段:

func main() {
    session, err := mgo.Dial(mongoURI())
    if err != nil {
        log.Fatal(err)
    }
    defer session.Close()

    systemsC := session.DB("").C("systems")

    flag.Parse()
    ctx := context.Background()
    kami.Context = ctx

    kami.Use("/api/", httpauth.SimpleBasicAuth(os.Getenv("BASIC_USERNAME"), os.Getenv("BASIC_PASSWORD")))

...

    kami.Get("/api/v1/systems", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
        systems := []alpha.System{}
        systemsMap := map[string][]alpha.System{}

        err := systemsC.Find(nil).All(&systems)
        if err != nil {
            log.Println(err.Error())
            http.Error(w, err.Error(), 404)
        }
        systemsMap["systems"] = systems

        err = json.NewEncoder(w).Encode(&systemsMap)
        if err != nil {
            http.Error(w, err.Error(), 500)
        }
        w.Header().Set("Content-Type", "application/json")
    })

    kami.Serve()
}

这是我用于进行GET请求的ReactJS代码:

componentDidMount() {
    fetch('http://localhost:8000/api/v1/systems') 
    .then(function(response) {
        return response.json()
    }).then(function(data) {
        this.setState({ data }, () => console.log(this.state));
    });
}

完整的URL需要凭据:http://user:password@localhost:8000/api/v1/systems

我尝试在我的kami.Get函数中添加各种头部,但仍然收到相同的错误:

w.Header().Set("Access-Control-Allow-Origin", "*") //当发送凭据时,此头部不起作用

还尝试了以下方法,但都无效:

w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")

现在我正在尝试使用rs/cors,但不确定如何将其添加到我的代码中。我只需要这三行代码吗:

mux := http.NewServeMux()
handler := cors.Default().Handler(mux)
http.ListenAndServe(":8080", handler)

不太确定如何混合使用mux、kami和cors,任何帮助将不胜感激,谢谢!

编辑

也许一个更简单的问题是,是否有人知道如何将corskami集成。我认为这可能会解决我的问题,只是不知道如何一起使用它们。

英文:

Hello I'm trying to access a GET request on a Golang api running on localhost:8000 from a ReactJS web app running on localhost:3000. But whenever I try to do this, I get the following error:

Fetch API cannot load http://localhost:8000/api/v1/systems.
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 401. 
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. 

Here's a snippet of my Go server code:

func main() {
    session, err := mgo.Dial(mongoURI())
    if err != nil {
	    log.Fatal(err)
    }
    defer session.Close()

    systemsC := session.DB("").C("systems")

    flag.Parse()
    ctx := context.Background()
    kami.Context = ctx

    kami.Use("/api/", httpauth.SimpleBasicAuth(os.Getenv("BASIC_USERNAME"), os.Getenv("BASIC_PASSWORD")))

...

    kami.Get("/api/v1/systems", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	    systems := []alpha.System{}
	    systemsMap := map[string][]alpha.System{}

	    err := systemsC.Find(nil).All(&systems)
	    if err != nil {
		    log.Println(err.Error())
		    http.Error(w, err.Error(), 404)
	    }
	    systemsMap["systems"] = systems

	    err = json.NewEncoder(w).Encode(&systemsMap)
	    if err != nil {
		    http.Error(w, err.Error(), 500)
	    }
	    w.Header().Set("Content-Type", "application/json")
    })

    kami.Serve()
}

Here's the ReactJS code I'm using to make the GET request:

componentDidMount() {
    fetch('http://localhost:8000/api/v1/systems') 
    .then(function(response) {
        return response.json()
    }).then(function(data) {
        this.setState({ data }, () => console.log(this.state));
    });
}

The complete URL requires credentials: http://user:password@localhost:8000/api/v1/systems

I've tried adding various headers to my kami.Get function, but keep getting the same error:

w.Header().Set("Access-Control-Allow-Origin", "*") //This header doesn't work when credentials are sent

Also tried these to no avail:

w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")

Right now I'm trying to use rs/cors, but not sure on how to add it to my code. Do I only need these 3 lines of code:

mux := http.NewServeMux()
handler := cors.Default().Handler(mux)
http.ListenAndServe(":8080", handler)

Not really sure how to mix mux, kami and cors, any help is appreciated, thank you!

EDIT

Maybe a much simpler question would be if anyone knows how to integrate cors with kami. I think this could fix my problem, just can't figure out how to use them together.

1: https://github.com/guregu/kami "kami"
2: https://github.com/rs/cors "rs/cors"

答案1

得分: 1

我刚刚创建了一个cors对象,并将其处理程序作为中间件传递给kami:

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

kami.Use("/api/", c.Handler)

现在我可以发送请求了。

英文:

I just had to create a cors object and pass its handler as middleware to kami:

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

kami.Use("/api/", c.Handler)

This let's me make requests now.

huangapple
  • 本文由 发表于 2016年11月16日 04:32:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/40619173.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定