Golang API中NextJS的fetch请求出现CORS错误怎么解决

Golang API中NextJS的fetch请求出现CORS错误怎么解决 我有一个使用Next.js的前端应用和一个Go语言编写的API。特别是在需要授权的端点上,每次都会返回这个错误。

WhatsApp Image 2024-01-29 at 19.40.40

控制器:

func RecoverUser(w http.ResponseWriter, r *http.Request) {
	userIDInToken, erro := authetication.ExtractUserID(r)
	if erro != nil {
		responses.Erro(w, http.StatusUnauthorized, erro)
		return
	}

	var user models.User
	record := database.Instance.First(&user, "id = ?", userIDInToken)
	if record.Error != nil {
		responses.Erro(w, http.StatusInternalServerError, record.Error)
		return
	}

	responses.JSON(w, http.StatusOK, user)
}

中间件:

func Authenticate(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := authetication.ValidateToken(r); err != nil {
			responses.Erro(w, http.StatusUnauthorized, err)
			return
		}
		next(w, r)
	}
}

func EnableCorsDevelopment(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// Permitir solicitações de qualquer origem
		w.Header().Set("Access-Control-Allow-Origin", config.FrontEndUrl)
		// Permitir os métodos HTTP especificados
		w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		// Permitir os cabeçalhos especificados
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

		w.Header().Set("Acess-Control-Allow-Credentials", "true")

		next(w, r)
	}
}

Next.js fetch调用:

useEffect(() => {
        if (Cookies.get('token')) {
            const token = Cookies.get('token')
            const fetchData = async () => {
                const response = await fetch(BASE_URL_API + '/recuperar/usuario', {
                method: 'GET',
                headers: {
                    'Content-type': 'application/json',
                    'Authorization': `Bearer ${token}` 
                    },
                })
                if (!response.ok) {
                    console.log('ERRO')
                } else {
                    const result = await response.json()
                    setUser(result.user)
                }
            }

            fetchData()
        }
    }, [])

更多关于Golang API中NextJS的fetch请求出现CORS错误怎么解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

你能展示一下你“使用”中间件的代码吗? 你能看到响应头吗?

更多关于Golang API中NextJS的fetch请求出现CORS错误怎么解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


嗨,Massimo!我通过在我的路由器中添加这些CORS选项解决了这个问题,NextJS的预检请求现在被接受了。

func main() {
	config.LoadEnvironment()

	database.Conect()
	database.Migrate()

	r := router.Generate()

	cors := cors.New(cors.Options{
        AllowedOrigins:   []string{config.FrontEndUrl},
        AllowedHeaders:   []string{"*"},
        AllowedMethods:   []string{"GET", "PATCH", "POST", "PUT", "OPTIONS", "DELETE"},
        AllowCredentials: true,
    })

	handler := cors.Handler(r)

	log.Printf("Escutando na porta %d\n", config.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", config.Port), handler))
}

在Go API中处理CORS问题,需要确保中间件正确处理OPTIONS预检请求。你的EnableCorsDevelopment中间件缺少对OPTIONS请求的处理,这会导致预检请求失败。

以下是修正后的中间件:

func EnableCorsDevelopment(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // 设置CORS头
        w.Header().Set("Access-Control-Allow-Origin", config.FrontEndUrl)
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
        w.Header().Set("Access-Control-Allow-Credentials", "true") // 注意拼写:Access-Control-Allow-Credentials

        // 处理OPTIONS预检请求
        if r.Method == "OPTIONS" {
            w.WriteHeader(http.StatusOK)
            return
        }

        next(w, r)
    }
}

另外,确保路由正确配置中间件顺序。CORS中间件应该在其他中间件之前:

// 路由配置示例
func ConfigureRoutes() {
    http.HandleFunc("/recuperar/usuario", 
        middleware.EnableCorsDevelopment(
            middleware.Authenticate(
                controllers.RecoverUser,
            ),
        ),
    )
}

对于生产环境,建议使用成熟的CORS库,如github.com/rs/cors

import "github.com/rs/cors"

func main() {
    c := cors.New(cors.Options{
        AllowedOrigins:   []string{config.FrontEndUrl},
        AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
        AllowedHeaders:   []string{"Content-Type", "Authorization"},
        AllowCredentials: true,
        Debug:            true, // 开发时启用调试
    })

    handler := c.Handler(http.DefaultServeMux)
    http.ListenAndServe(":8080", handler)
}

确保Next.js fetch调用包含credentials选项:

const response = await fetch(BASE_URL_API + '/recuperar/usuario', {
    method: 'GET',
    headers: {
        'Content-type': 'application/json',
        'Authorization': `Bearer ${token}` 
    },
    credentials: 'include' // 确保发送凭据
})

检查config.FrontEndUrl是否正确配置为Next.js应用的URL,例如http://localhost:3000

回到顶部