Go开发API在Postman正常,JavaScript调用报跨域错误
解决Go API跨域问题:预检请求Access-Control-Allow-Origin为null错误
嘿,这个问题我太熟了——这就是浏览器的**跨域资源共享(CORS)**限制在搞鬼!Postman这类工具不会像浏览器那样严格执行CORS规则,所以你的API在Postman里能正常跑,但前端JS调用时,浏览器会先发送一个OPTIONS类型的「预检请求」,检查你的API是否允许跨域访问。如果你的API没正确处理这个预检请求,或者没返回正确的CORS响应头,就会弹出这个错误。
下面给你两种靠谱的解决办法:
方法1:手动写个CORS中间件
自己写个简单的中间件,给所有请求加上必要的CORS响应头,还能直接处理OPTIONS预检请求:
package main import ( "encoding/json" "github.com/gorilla/mux" "log" "net/http" "strconv" ) type Calculate struct { Operand1 string `json:"Operand1,omitempty"` Operand2 string `json:"Operand2,omitempty"` Operator string `json:"Operator,omitempty"` } type Answer struct { Res float64 `json:"Res,omitempty"` } // CORS中间件,给请求加跨域头 func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 允许的源,生产环境别用*,换成你的前端域名比如"http://localhost:3000" w.Header().Set("Access-Control-Allow-Origin", "*") // 允许的请求方法 w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") // 允许的请求头,比如Content-Type是POST请求必须的 w.Header().Set("Access-Control-Allow-Headers", "Content-Type") // 处理浏览器的OPTIONS预检请求,直接返回200就行 if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } // 继续走后续的业务逻辑 next.ServeHTTP(w, r) }) } func calculateHandler(w http.ResponseWriter, r *http.Request) { var calc Calculate err := json.NewDecoder(r.Body).Decode(&calc) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } res := 0.0 switch calc.Operator { case "+": op1, _ := strconv.ParseFloat(calc.Operand1, 64) op2, _ := strconv.ParseFloat(calc.Operand2, 64) res = op1 + op2 // 这里可以加其他操作符的逻辑,比如-、*、/ } json.NewEncoder(w).Encode(Answer{Res: res}) } func main() { r := mux.NewRouter() // 给所有路由加上CORS中间件 r.Use(corsMiddleware) r.HandleFunc("/calculate", calculateHandler).Methods("POST") log.Fatal(http.ListenAndServe(":8080", r)) }
方法2:用gorilla官方的handlers包处理CORS
不想自己写中间件?直接用gorilla官方提供的handlers包,配置更灵活:
- 先安装这个包:
go get github.com/gorilla/handlers
- 修改你的main函数,用CORS包装路由:
package main import ( "encoding/json" "github.com/gorilla/mux" "github.com/gorilla/handlers" "log" "net/http" "strconv" ) // 结构体和calculateHandler函数和上面一样... func main() { r := mux.NewRouter() r.HandleFunc("/calculate", calculateHandler).Methods("POST") // 配置CORS规则 corsConfig := handlers.CORS( handlers.AllowedOrigins([]string{"*"}), // 生产环境替换为你的前端域名 handlers.AllowedMethods([]string{"POST", "OPTIONS"}), handlers.AllowedHeaders([]string{"Content-Type"}), ) // 用CORS中间件包装路由后启动服务 log.Fatal(http.ListenAndServe(":8080", corsConfig(r))) }
最后提醒下:
- 生产环境绝对不要用
*作为允许的源,一定要指定具体的前端域名,比如"https://your-frontend-app.com",避免安全风险。 - 必须确保你的API能处理OPTIONS请求,因为浏览器的预检请求就是OPTIONS类型的,如果路由只允许POST,没处理OPTIONS,预检肯定失败。
内容的提问来源于stack exchange,提问作者Priya S
相关产品推荐
相关产品推荐

