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请求前会:
- 进行preflight验证是否允许DELETE请求,方法是发送一个OPTIONS请求;
- 后端需要在返回header中表明允许的请求方法;
- 浏览器发出真正的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

浙公网安备 33010602011771号