新聞中心
允許接口跨域往往是需要結(jié)合 路由管理-中間件/攔截器 一起使用,來統(tǒng)一設(shè)置某些路由規(guī)則下的接口可以跨域訪問。同時(shí),針對(duì)允許?WebSocket?的跨域請(qǐng)求訪問,也是通過該方式來實(shí)現(xiàn)。

相關(guān)方法: https://pkg.GO.dev/github.com/gogf/gf/v2/net/ghttp#Response
func (r *Response) CORS(options CORSOptions)
func (r *Response) CORSAllowedOrigin(options CORSOptions) bool
func (r *Response) CORSDefault()
func (r *Response) DefaultCORSOptions() CORSOptionsCORS對(duì)象
?CORS?是?W3?互聯(lián)網(wǎng)標(biāo)準(zhǔn)組織對(duì)?HTTP?跨域請(qǐng)求的標(biāo)準(zhǔn),在?ghttp?模塊中,我們可以通過?CORSOptions?對(duì)象來管理對(duì)應(yīng)的跨域請(qǐng)求選項(xiàng)。定義如下:
// See https://www.w3.org/TR/cors/ .
// 服務(wù)端允許跨域請(qǐng)求選項(xiàng)
type CORSOptions struct {
AllowDomain []string // Used for allowing requests from custom domains
AllowOrigin string // Access-Control-Allow-Origin
AllowCredentials string // Access-Control-Allow-Credentials
ExposeHeaders string // Access-Control-Expose-Headers
MaxAge int // Access-Control-Max-Age
AllowMethods string // Access-Control-Allow-Methods
AllowHeaders string // Access-Control-Allow-Headers
}具體參數(shù)的介紹請(qǐng)查看W3組織 官網(wǎng)手冊(cè)。
CORS配置
默認(rèn)CORSOptions
當(dāng)然,為方便跨域設(shè)置,在?ghttp?模塊中也提供了默認(rèn)的跨域請(qǐng)求選項(xiàng),通過?DefaultCORSOptions?方法獲取。大多數(shù)情況下,我們?cè)谛枰试S跨域請(qǐng)求的接口中(一般情況下使用中間件)可以直接使用?CORSDefault()?允許該接口跨域訪問。
限制Origin來源
大多數(shù)時(shí)候,我們需要限制請(qǐng)求來源為我們受信任的域名列表,我們可以使用?AllowDomain?配置,使用方式:
// 允許跨域請(qǐng)求中間件
func Middleware(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"GoFrame.org", "johng.cn"}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}OPTIONS請(qǐng)求
有的客戶端,部分瀏覽器在發(fā)送?AJAX?請(qǐng)求之前會(huì)首先發(fā)送?OPTIONS?預(yù)請(qǐng)求檢測后續(xù)請(qǐng)求是否允許發(fā)送。?GF?框架的?Server?完全遵守?W3C?關(guān)于?OPTIONS?請(qǐng)求方法的規(guī)范約定,因此只要服務(wù)端設(shè)置好?CORS?中間件,?OPTIONS?請(qǐng)求也將會(huì)自動(dòng)支持。
示例1,基本使用
我們來看一個(gè)簡單的接口示例:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
}接口地址是 http://localhost/api.v1/order ,當(dāng)然這個(gè)接口是不允許跨域的。我們打開一個(gè)不同的域名,例如:百度首頁(正好用了?jQuery?,方便調(diào)試),然后按?F12?打開開發(fā)者面板,在?console?下執(zhí)行以下?AJAX?請(qǐng)求:
$.get("http://localhost:8199/api.v1/order", function(result){
console.log(result)
});結(jié)果如下:
返回了不允許跨域請(qǐng)求的提示錯(cuò)誤,接著我們修改一下服務(wù)端接口的測試代碼,如下:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareCORS(r *ghttp.Request) {
r.Response.CORSDefault()
r.Middleware.Next()
}
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
}我們?cè)黾恿酸槍?duì)于路由?/api.v1?的前置中間件?MiddlewareCORS?,該事件將會(huì)在所有服務(wù)執(zhí)行之前調(diào)用。我們通過調(diào)用?CORSDefault?方法使用默認(rèn)的跨域設(shè)置允許跨域請(qǐng)求。該綁定的事件路由規(guī)則使用了模糊匹配規(guī)則,表示所有?/api.v1?開頭的接口地址都允許跨域請(qǐng)求。
返回剛才的百度首頁,再次執(zhí)行請(qǐng)求?AJAX?請(qǐng)求,這次便成功了:
當(dāng)然我們也可以通過?CORSOptions?對(duì)象以及?CORS?方法對(duì)跨域請(qǐng)求做更多的設(shè)置。
示例2,授權(quán)跨域Origin
在大多數(shù)場景中,我們是需要自定義授權(quán)跨域的?Origin?,那么我們可以將以上的例子改進(jìn)如下,在該示例中,我們僅允許?goframe.org?及?baidu.com?跨域請(qǐng)求訪問。
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareCORS(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"goframe.org", "baidu.com"}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
}示例3,自定義檢測授權(quán)
不知大家是否有注意,在以上的示例中有個(gè)細(xì)節(jié),即使當(dāng)前接口不允許跨域訪問,但是只要接口被調(diào)用,接口完整邏輯仍會(huì)被執(zhí)行,在服務(wù)端其實(shí)也已經(jīng)走完了一次請(qǐng)求流程。針對(duì)于這個(gè)問題,我們可以通過自定義授權(quán)?Origin?并在中間件中通過?CORSAllowedOrigin?方法來做判斷,如果當(dāng)前請(qǐng)求的?Origin?在服務(wù)端是被允許執(zhí)行的,那么才會(huì)執(zhí)行后續(xù)流程,否則便會(huì)終止執(zhí)行。
在以下示例中,僅允許來自?goframe.org?域名的跨域請(qǐng)求,而來自其他域名的請(qǐng)求將會(huì)失敗并返回?403?:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareCORS(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"goframe.org"}
if !r.Response.CORSAllowedOrigin(corsOptions) {
r.Response.WriteStatus(http.StatusForbidden)
return
}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}
func Order(r *ghttp.Request) {
r.Response.Write("GET")
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()
} 當(dāng)前標(biāo)題:創(chuàng)新互聯(lián)GoFrame教程:GoFrame 高級(jí)特性-CORS跨域處理
當(dāng)前網(wǎng)址:http://www.dlmjj.cn/article/cooidjh.html


咨詢
建站咨詢
