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

控制器:
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
你能展示一下你“使用”中间件的代码吗? 你能看到响应头吗?
更多关于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。

