Golang中使用gorilla/handlers包遇到的CORS问题如何解决
Golang中使用gorilla/handlers包遇到的CORS问题如何解决 我有以下CORS配置:
headersOk := handlers.AllowedHeaders([]string{"Authorization", "Content-Type", "Origin", "Accept", "Accept-Language", "Accept-Encoding", "Cache-Control", "Content-Length", "X-Requested-With"})
originsOk := handlers.AllowedOrigins([]string{"http://localhost:8080", "http://localhost:5000"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":"+port, handlers.CORS(handlers.AllowCredentials(), originsOk, headersOk, methodsOk)(router)))
对于上述CORS配置,当使用Content-Type: application/json时,来自JavaScript XMLHttpRequest的请求工作正常。但是,当请求的Content-Type为multipart/form-data; boundary=someboundary时,会抛出以下错误:
Access to XMLHttpRequest at ‘https://example.com/profile/edit’ from origin ‘http://localhost:5000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
请帮忙解释为什么multipart/form-data请求会触发CORS拦截。
更多关于Golang中使用gorilla/handlers包遇到的CORS问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
您的CORS允许的域名中不包含 example.com。
CORS中存在一个简单请求的判断。如果一个请求是简单请求,则不需要进行CORS预检,会直接使用CORS策略进行判断。
简单请求要求请求方法是 HEAD、GET、POST 中的一种;请求头仅包含 Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type,没有额外的自定义头;并且 Content-Type 的值是 application/x-www-form-urlencoded、multipart/form-data、text/plain 三者之一。
更多信息请自行搜索。
更多关于Golang中使用gorilla/handlers包遇到的CORS问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
问题在于multipart/form-data请求会触发浏览器发送预检请求(preflight request),而预检请求的Content-Type头部值会包含boundary参数。你的配置中只允许Content-Type为application/json,没有包含multipart/form-data。
当浏览器发送multipart/form-data请求时,会先发送一个OPTIONS方法的预检请求,其Content-Type头部值为multipart/form-data; boundary=someboundary。由于这个值不在你配置的AllowedHeaders列表中,CORS中间件会拒绝该请求。
解决方案是修改AllowedHeaders配置,允许multipart/form-data的Content-Type头部:
headersOk := handlers.AllowedHeaders([]string{
"Authorization",
"Content-Type",
"Origin",
"Accept",
"Accept-Language",
"Accept-Encoding",
"Cache-Control",
"Content-Length",
"X-Requested-With",
})
实际上,handlers.AllowedHeaders配置的是服务器允许客户端发送的头部列表,而不是Access-Control-Allow-Headers响应头部的值。对于Content-Type,你只需要在列表中包含Content-Type即可,不需要指定具体的MIME类型。
完整示例:
package main
import (
"log"
"net/http"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
)
func main() {
router := mux.NewRouter()
router.HandleFunc("/profile/edit", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"ok"}`))
})
headersOk := handlers.AllowedHeaders([]string{
"Authorization",
"Content-Type", // 只需要包含Content-Type,不需要指定具体类型
"Origin",
"Accept",
"Accept-Language",
"Accept-Encoding",
"Cache-Control",
"Content-Length",
"X-Requested-With",
})
originsOk := handlers.AllowedOrigins([]string{
"http://localhost:8080",
"http://localhost:5000",
})
methodsOk := handlers.AllowedMethods([]string{
"GET", "HEAD", "POST", "PUT", "OPTIONS",
})
port := "8080"
log.Fatal(http.ListenAndServe(":"+port,
handlers.CORS(
handlers.AllowCredentials(),
originsOk,
headersOk,
methodsOk,
)(router),
))
}
这样配置后,浏览器发送的multipart/form-data; boundary=someboundary请求就能正常通过CORS检查了。

