目录
一、了解跨域问题
二、Go Zero 中解决跨域的方式
(一)使用中间件实现跨域(推荐)
(二)通过配置服务器响应头实现跨域(较简单但不够灵活)
跨域是指浏览器出于安全考虑,限制了从一个源(协议、域名、端口)向另一个源发起的请求。例如,前端应用运行在 http://localhost:8080
,而后端 API 部署在 http://api.example.com:80
,此时前端发起的请求就属于跨域请求,浏览器会默认阻止这类请求,除非后端进行了合适的跨域配置。
middleware
目录下创建一个名为 corsMiddleware.go
的文件(目录结构可根据实际项目调整),代码示例如下:package middleware
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
)
// CorsMiddleware 跨域中间件
func CorsMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 设置允许的源
w.Header().Set("Access-Control-Allow-Origin", "*")
// 设置允许的请求头类型
w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
// 设置允许的请求方法
w.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
// 允许携带凭证(如 Cookie 等,根据实际需求决定是否设置)
w.Header().Set("Access-Control-Allow-Credentials", "true")
if r.Method == http.MethodOptions {
// 对于 OPTIONS 请求,直接返回 200 状态码
httpx.WriteJson(w, http.StatusOK, map[string]interface{}{})
return
}
next(w, r)
}
}
在上述代码中,这个中间件函数主要完成了以下几件事:
Access-Control-Allow-Origin
为 *
,表示允许来自任意源的请求(在实际生产环境中,建议明确指定允许的源,以增强安全性)。Content-Type
和 Authorization
,可根据实际需求添加更多。OPTIONS
预检请求(浏览器在正式发起跨域请求前会先发送 OPTIONS 请求来确认是否允许跨域),直接返回 200
状态码,避免后续请求被拦截。main.go
文件(或者路由配置相关文件)中有如下代码来初始化路由和启动服务:package main
import (
"net/http"
"github.com/zeromicro/go-zero/rest"
"your-project/middleware" // 引入刚才创建的中间件所在包
)
func main() {
// 创建 RESTful 服务实例
srv := rest.MustNewServer(rest.RestConf{
// 配置服务相关参数,如地址、端口等
Address: ":8080",
})
// 为路由添加跨域中间件
srv.Use(middleware.CorsMiddleware)
// 注册路由,这里假设你有一个简单的路由注册逻辑,比如如下示例
handler := yourHandler{}
srv.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/api/hello",
Handler: handler.Hello,
},
},
)
// 启动服务
srv.Start()
}
通过调用 srv.Use(middleware.CorsMiddleware)
,就将跨域中间件应用到了整个服务的路由上,这样所有经过该服务的请求都会先经过这个跨域中间件处理,满足跨域条件的请求就能正常被后端接收和处理了。
如果不想单独创建中间件,也可以直接在路由处理函数中针对每个响应手动设置跨域相关的响应头,示例如下:
package main
import (
"net/http"
"github.com/zeromicro/go-zero/rest"
)
type HelloHandler struct{}
func (h HelloHandler) Hello(w http.ResponseWriter, r *http.Request) {
// 设置允许的源
w.Header().Set("Access-Control-Allow-Origin", "*")
// 设置允许的请求头类型
w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
// 设置允许的请求方法
w.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
// 允许携带凭证(根据实际需求决定是否设置)
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Write([]byte("Hello, World!"))
}
func main() {
srv := rest.MustNewServer(rest.RestConf{
Address: ":8080",
})
handler := HelloHandler{}
srv.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/api/hello",
Handler: handler.Hello,
},
},
)
srv.Start()
}
不过这种方式不够灵活,每次新增路由处理函数都需要重复设置这些跨域响应头,而且不利于统一管理,所以更推荐使用中间件的方式来实现跨域配置。
通过上述步骤,就可以在 Go Zero 框架下有效地解决跨域问题,确保前端跨域请求能够顺利与后端进行交互。