Loading

go后端增加CORS支持

背景

使用vue做前端,go做后端,无法调用后端api报错blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource请求失败。

含义

Cross-Origin Resource Sharing (CORS)发生在浏览器请求与自身origin(domain, protocol, port)不一致时,默认情况下浏览器受到"same-origin policy"制约,请求被限制在相同origin内。

解决

给后端响应header增加Access-Control-Allow-Origin信息

package main
import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/cors"
)

func main() {
	r := gin.Default()
	// Enable CORS
	middleware := cors.New(cors.Config{
		AllowOrigins:     []string{"*"}, // For development only, restrict in production
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Accept"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	})
	// Create an API group
	api := r.Group("/api", middleware)
	{
		// your HandlerFunc
	}
}

问题

上述代码遇到DELETE请求时无法正常调用,控制台报错Preflight Request Failed。
后端日志有显示OPTIONS请求404并无DELETE发生。
手动发起DELETE请求调试正常说明问题出在浏览器,抓取正常DELETE流程:

// Preflight Request (sent by browser)
OPTIONS /api/resource/123 HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Authorization

// Server Response to Preflight
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 86400

// Actual DELETE Request (sent by browser, if preflight allowed)
DELETE /api/resource/123 HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Authorization: Bearer <token>

查阅文献得知浏览器在进行DELETE请求前会:

  1. 进行preflight验证是否允许DELETE请求,方法是发送一个OPTIONS请求;
  2. 后端需要在返回header中表明允许的请求方法;
  3. 浏览器发出真正的DELETE请求。
    原始代码/api路由下未注册OPTIONS方法,改为对整个路由应用CROS中间件。
    代码修改:
package main
import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/cors"
)

func main() {
	r := gin.Default()
	// Enable CORS
	middleware := cors.New(cors.Config{
		AllowOrigins:     []string{"*"}, // For development only, restrict in production
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Accept"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	})
	// Apply for all
	r.Use(middleware)
	// Create an API group
	api := r.Group("/api")
	{
		// your HandlerFunc
	}
}

参考

gin-contrib/cors: Official CORS gin's middleware
What is a Preflight Request - A short definition

posted @ 2025-10-09 11:49  azureology  阅读(6)  评论(0)    收藏  举报