Heroku/Go在处理CORS和远程请求方面出现问题。

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

Heroku/Go trouble with CORS, remote request

问题

我在Heroku上有一个用Go编写的后端,我的前端由另一个Go应用程序提供服务。我试图从前端向后端发出请求,但是出现了以下错误:

跨域请求被阻止:同源策略禁止读取 https://grafulator.herokuapp.com/login 的远程资源。(原因:缺少CORS头‘Access-Control-Allow-Origin’)。状态码:404。

我理解这个错误,以及我需要在每个路由的后端头部设置的问题。我尝试过这样做,但问题并没有解决。

在Postman中向后端发出的请求是有效的,但是当我尝试从Web浏览器(无论是本地还是在Heroku上提供服务的前端)发出这些请求时,问题就出现了。

我尝试过以下方法:

router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    if r.Header.Get("Access-Control-Request-Method") != "" {
        // 设置CORS头部
        header := w.Header()
        header.Set("Access-Control-Allow-Methods", header.Get("Allow"))
        header.Set("Access-Control-Allow-Origin", "*")
    }

    // 调整状态码为204
    w.WriteHeader(http.StatusNoContent)
})
w.Header().Set("Access-Control-Allow-Origin", "*")
func main() {
    // BasicAuth用户名和密码
    user := ""
    pass := ""

    port := os.Getenv("PORT")
    if port == "" {
        port = "9000" // 如果未指定端口,则使用默认端口
    }

    DefaultUser()

    // HTTPRouter设置和路由
    router := httprouter.New()
    router.POST("/login/", BasicAuth(RouteLogin, user, pass))
    router.POST("/upload/", JWTAuth(RouteUpload))

    c := cors.New(cors.Options{
        AllowedOrigins: []string{"*"},
        AllowedMethods: []string{"GET", "POST", "DELETE", "PUT", "OPTIONS"},
    })
    fmt.Println(http.ListenAndServe(":"+port, c.Handler(router)))
}
handler := cors.AllowAll().Handler(router)
fmt.Println(http.ListenAndServe(":8081", handler))

希望这些尝试能对你有所帮助。

英文:

I have a backend in Go on Heroku, and my frontend is being served by another Go app on Heroku. I am trying to make requests to the backend from the frontend and I am getting this error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://grafulator.herokuapp.com/login. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 404.

I understand the error, and that it is something I need to set in the backends header for each route. I have tried doing this and it does not solve the problem.

The requests work in Postman to the backend, but the problem comes when I try to make these requests from a web browser, either locally or my frontend served on heroku.

Things I have tried:

router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    if r.Header.Get("Access-Control-Request-Method") != "" {
        // Set CORS headers
        header := w.Header()
        header.Set("Access-Control-Allow-Methods", header.Get("Allow"))
        header.Set("Access-Control-Allow-Origin", "*")
    }

    // Adjust status code to 204
    w.WriteHeader(http.StatusNoContent)
})
w.Header().Set("Access-Control-Allow-Origin", "*")
func main() {
	// BasicAuth username and password
	user := ""
	pass := ""

	port := os.Getenv("PORT")
	if port == "" {
		port = "9000" // Default port if not specified
	}

	DefaultUser()

	// HTTPRouter Settings and Routes
	router := httprouter.New()
	router.POST("/login/", BasicAuth(RouteLogin, user, pass))
	router.POST("/upload/", JWTAuth(RouteUpload))

	c := cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedMethods: []string{"GET", "POST", "DELETE", "PUT", "OPTIONS"},
	})
	fmt.Println(http.ListenAndServe(":"+port, c.Handler(router)))
}
handler := cors.AllowAll().Handler(router)
fmt.Println(http.ListenAndServe(":8081", handler))

答案1

得分: 1

CORS只会在浏览器中发生。浏览器发送一个OPTIONS方法的预检请求,以检查是否允许发送原始请求。

如果你使用以下代码,它会正常工作。你不需要任何额外的CORS设置。只需删除与CORS相关的其他代码。

后端:

package main

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"github.com/rs/cors"
	"net/http"
	"os"
)

func main() {

	port := os.Getenv("PORT")
	if port == "" {
		port = "9000" // 如果未指定端口,则使用默认端口
	}

	router := httprouter.New()
	router.GET("/upload", func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
		writer.Write([]byte("test body"))
	})

	handler := cors.AllowAll().Handler(router)
	fmt.Println(http.ListenAndServe(":"+port, handler))
}

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>
        fetch("http://localhost:9000/upload")
    </script>
</head>
<body>

</body>
</html>

响应:
成功案例

如果你用以下代码替换main.go中的最后两行,你将再次得到CORS错误。

fmt.Println(http.ListenAndServe(":"+port, router))
英文:

CORS only happens on the browser. Browser sends a preflight request whose method is OPTION to check if it is allowed to send the original requests.

If you use the following code, it works. You do not need any extra CORS setting. Just remove the other codes regarding CORS.

Backend:

package main

import (
	&quot;fmt&quot;
	&quot;github.com/julienschmidt/httprouter&quot;
	&quot;github.com/rs/cors&quot;
	&quot;net/http&quot;
	&quot;os&quot;
)

func main() {

	port := os.Getenv(&quot;PORT&quot;)
	if port == &quot;&quot; {
		port = &quot;9000&quot; // Default port if not specified
	}

	router := httprouter.New()
	router.GET(&quot;/upload&quot;, func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
		writer.Write([]byte(&quot;test body&quot;))
	})

	handler := cors.AllowAll().Handler(router)
	fmt.Println(http.ListenAndServe(&quot;:&quot;+port, handler))
}


Frontend

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;Title&lt;/title&gt;

    &lt;script&gt;
        fetch(&quot;http://localhost:9000/upload&quot;)
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;/body&gt;
&lt;/html&gt;

Response:
Succes Case

If you replace last two lines in main.go with the following line, you will get CORS error again.

fmt.Println(http.ListenAndServe(&quot;:&quot;+port, router))

huangapple
  • 本文由 发表于 2022年5月21日 00:33:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/72322128.html
匿名

发表评论

匿名网友

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

确定