Golang 實(shí)現(xiàn)跨域請(qǐng)求的多種實(shí)現(xiàn)對(duì)比
1. 原生 net/http 手動(dòng)設(shè)置 CORS 頭
通過(guò)原生庫(kù)手動(dòng)設(shè)置 HTTP 響應(yīng)頭,處理 OPTIONS
預(yù)檢請(qǐng)求。
實(shí)現(xiàn)示例:
func CORS(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(http.StatusNoContent) return } c.Next() } func main() { r := gin.Default() r.Use(CORS) r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run(":8080") }
優(yōu)點(diǎn):
零依賴:無(wú)需引入第三方庫(kù)。
完全控制:可自定義所有 CORS 相關(guān)頭信息。
缺點(diǎn):
冗余代碼:需在每個(gè)路由中重復(fù)設(shè)置頭信息。
易出錯(cuò):手動(dòng)處理
OPTIONS
預(yù)檢請(qǐng)求可能遺漏細(xì)節(jié)(如動(dòng)態(tài)Origin
校驗(yàn))。維護(hù)困難:復(fù)雜場(chǎng)景(如多域名白名單)需要自行實(shí)現(xiàn)邏輯。
適用場(chǎng)景:簡(jiǎn)單項(xiàng)目或少量 API 端點(diǎn)。
2. 使用第三方庫(kù) rs/cors
通過(guò)流行的開(kāi)源庫(kù) GitHub - rs/cors: Go net/http configurable handler to handle CORS requests 簡(jiǎn)化 CORS 配置。
實(shí)現(xiàn)示例:
package main import ( "net/http" "github.com/rs/cors" ) func main() { mux := http.NewServeMux() mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, CORS!")) }) // 配置 CORS c := cors.New(cors.Options{ AllowedOrigins: ["https://example.com", "http://localhost:3000"], AllowedMethods: ["GET", "POST", "PUT", "DELETE"], AllowedHeaders: ["Content-Type", "Authorization"], AllowCredentials: true, Debug: false, }) handler := c.Handler(mux) http.ListenAndServe(":8080", handler) }
優(yōu)點(diǎn):
開(kāi)箱即用:自動(dòng)處理
OPTIONS
預(yù)檢請(qǐng)求和頭信息。靈活配置:支持域名白名單、HTTP 方法、自定義頭等。
安全可靠:內(nèi)置動(dòng)態(tài)
Origin
校驗(yàn)和憑據(jù)(Cookies)支持。
缺點(diǎn):
引入依賴:需管理第三方庫(kù)版本。
適用場(chǎng)景:大多數(shù)項(xiàng)目,尤其是需要復(fù)雜 CORS 配置的情況。
3. Web 框架中間件(如 Gin、Echo)
主流 Web 框架(如 Gin、Echo)通常內(nèi)置或提供 CORS 中間件。
Gin 框架示例:
package main import ( "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // 配置 CORS 中間件 r.Use(cors.New(cors.Config{ AllowOrigins: ["https://example.com"], AllowMethods: ["GET", "POST"], AllowHeaders: ["Content-Type"], ExposeHeaders: ["Content-Length"], AllowCredentials: true, MaxAge: 12 * time.Hour, })) r.GET("/api", func(c *gin.Context) { c.String(200, "Hello, CORS!") }) r.Run(":8080") }
優(yōu)點(diǎn):
框架集成:與路由、中間件等無(wú)縫協(xié)作。
簡(jiǎn)化配置:語(yǔ)法與框架風(fēng)格一致,通常比原生更簡(jiǎn)潔。
缺點(diǎn):
框架綁定:僅適用于特定框架(如 Gin、Echo)。
適用場(chǎng)景:已使用特定 Web 框架的項(xiàng)目。
4. 反向代理層處理(如 Nginx)
在反向代理(如 Nginx)中設(shè)置 CORS 頭,無(wú)需修改 Go 代碼。
Nginx 配置示例:
location /api { add_header 'Access-Control-Allow-Origin' 'https://example.com'; add_header 'Access-Control-Allow-Methods' 'GET, POST'; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization'; if ($request_method = OPTIONS) { return 204; } proxy_pass http://localhost:8080; }
優(yōu)點(diǎn):
解耦業(yè)務(wù)代碼:跨域與業(yè)務(wù)邏輯分離。
集中管理:適合微服務(wù)架構(gòu)統(tǒng)一配置。
缺點(diǎn):
依賴運(yùn)維:需熟悉 Nginx 配置,不適合無(wú)代理的小型項(xiàng)目。
適用場(chǎng)景:已有反向代理層或需要統(tǒng)一管理 CORS 的環(huán)境。
對(duì)比與選型建議
方式 | 維護(hù)成本 | 靈活性 | 依賴項(xiàng) | 適用場(chǎng)景 |
---|---|---|---|---|
原生手動(dòng)設(shè)置 | 高 | 高 | 無(wú) | 簡(jiǎn)單 API、快速原型 |
rs/cors 庫(kù) | 低 | 中高 | 第三方庫(kù) | 大多數(shù)項(xiàng)目 |
Web 框架中間件 | 低 | 中 | 框架 | 已使用對(duì)應(yīng)框架的項(xiàng)目 |
反向代理(如 Nginx) | 中 | 中 | 運(yùn)維環(huán)境 | 微服務(wù)、已有代理層的項(xiàng)目 |
推薦選擇:
快速開(kāi)發(fā):優(yōu)先使用
rs/cors
或框架中間件。復(fù)雜企業(yè)級(jí):結(jié)合反向代理和中間件,實(shí)現(xiàn)多層控制。
極簡(jiǎn)場(chǎng)景:原生手動(dòng)設(shè)置(但需注意安全風(fēng)險(xiǎn))。
關(guān)鍵注意事項(xiàng)
安全限制:避免濫用
Access-Control-Allow-Origin: *
,應(yīng)指定明確的白名單。預(yù)檢請(qǐng)求:確保正確處理
OPTIONS
方法,否則復(fù)雜請(qǐng)求(如帶自定義頭的 POST)會(huì)失敗。憑據(jù)(Cookies):若需跨域傳遞 Cookies,需設(shè)置
AllowCredentials: true
并明確指定Origin
(不能為*
)。
通過(guò)合理選擇跨域方案,可以在安全性和開(kāi)發(fā)效率之間取得平衡。
到此這篇關(guān)于Golang 實(shí)現(xiàn)跨域請(qǐng)求的多種實(shí)現(xiàn)對(duì)比的文章就介紹到這了,更多相關(guān)Golang 跨域請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文帶你理解Golang中的Time結(jié)構(gòu)
根據(jù)golang的time包的文檔可以知道,golang的time結(jié)構(gòu)中存儲(chǔ)了兩種時(shí)鐘,一種是Wall?Clocks,一種是Monotonic?Clocks,下面我們就來(lái)簡(jiǎn)單了解一下這兩種結(jié)構(gòu)吧2023-09-09Go 語(yǔ)言中的select語(yǔ)句詳解及工作原理
在Go語(yǔ)言中,select語(yǔ)句是用于處理多個(gè)通道(channel)操作的一種控制結(jié)構(gòu),它類似于 switch 語(yǔ)句,本文給大家介紹Go 語(yǔ)言中的select語(yǔ)句詳解及工作原理,感興趣的朋友一起看看吧2025-04-04Go語(yǔ)言學(xué)習(xí)筆記之文件讀寫操作詳解
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言對(duì)文件進(jìn)行讀寫操作的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下2022-05-05golang創(chuàng)建文件目錄os.Mkdir,os.MkdirAll的區(qū)別說(shuō)明
本文主要講述os.Mkdir、os.MkdirAll區(qū)別以及在創(chuàng)建文件目錄過(guò)程中的一些其他技巧,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03Go的gin參數(shù)校驗(yàn)中的validator庫(kù)詳解
這篇文章主要介紹了Go的gin參數(shù)校驗(yàn)之validator庫(kù),使用 validator 以后,只需要在定義結(jié)構(gòu)體時(shí)使用 binding 或 validate tag標(biāo)識(shí)相關(guān)校驗(yàn)規(guī)則,就可以進(jìn)行參數(shù)校驗(yàn)了,而不用自己?jiǎn)为?dú)去寫常見(jiàn)的校驗(yàn)規(guī)則,需要的朋友可以參考下2023-08-08Go?interface?接口的最佳實(shí)踐經(jīng)驗(yàn)分享
go?的接口在go的編程里面用的十分頻繁,尤其是空接口的使用,因?yàn)橛辛私涌?,才使得Go語(yǔ)言變得異常的強(qiáng)大,今天給大家介紹下Go?interface?接口的最佳實(shí)踐經(jīng)驗(yàn)分享,感興趣的朋友一起看看吧2022-04-04