Golang中如何全局启用OPTIONS请求
Golang中如何全局启用OPTIONS请求 我正在使用 Go 1.22 中的 HTTP 处理器,但是 OPTIONS 请求会被自动拒绝,并向客户端返回 405 状态码。因此,我无法从我的单页应用(SPA)中调用任何 POST 端点。有没有办法在不使用第三方工具或库的情况下,全局自动允许 OPTIONS 请求?
Ester:
有没有办法自动允许OPTIONS请求
我是这样处理的:
switch r.Method {
case "GET":
Read(w, r)
case "DELETE":
Delete(w, r)
case "POST":
Create(w, r)
case "PUT":
Update(w, r)
case "OPTIONS":
// bugfix (handshake)
default:
Read(w, r)
}
更多关于Golang中如何全局启用OPTIONS请求的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你可以直接使用类似这样的代码:
func newAppMux() *http.ServeMux {
router := http.NewServeMux()
// 全局 OPTIONS 请求处理器
router.HandleFunc("OPTIONS /", handleOptions)
return router
}
func handleOptions(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "https://myapp.com")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization")
w.WriteHeader(http.StatusOK)
}
关于模式中的“/”需要注意。根据文档:
特殊的通配符 {$} 仅匹配 URL 的结尾。例如,模式“/{$}”仅匹配路径“/”,而模式“/”匹配所有路径。
因此,该模式会匹配该HTTP方法(“OPTIONS”)下的所有路径。如需进一步了解CORS以及可能需要设置哪些请求头,请查阅此文档。
不过,没有必要为 CORS 声明一个全局的 OPTIONS 处理器;而且,与其手动实现 CORS(这容易出错),我建议使用专门的库。下面是一个示例:
package main
import (
"io"
"log"
"net/http"
"github.com/jub0bs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", handleHello) // 注意:未配置 CORS
// 创建 CORS 中间件
corsMw, err := cors.NewMiddleware(cors.Config{
Origins: []string{"https://example.com"},
Methods: []string{http.MethodGet, http.MethodPost},
RequestHeaders: []string{"Authorization"},
})
if err != nil {
log.Fatal(err)
}
corsMw.SetDebug(true) // 开启调试模式(可选)
api := http.NewServeMux()
api.HandleFunc("GET /users", handleUsersGet)
api.HandleFunc("POST /users", handleUsersPost)
mux.Handle("/api/", http.StripPrefix("/api", corsMw.Wrap(api))) // 注意:此处使用无方法模式
log.Fatal(http.ListenAndServe(":8080", mux))
}
func handleHello(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello, World!")
}
func handleUsersGet(w http.ResponseWriter, _ *http.Request) {
// 省略
}
func handleUsersPost(w http.ResponseWriter, _ *http.Request) {
// 省略
}
在Go中,HTTP处理器默认会拒绝OPTIONS请求并返回405状态码。要全局启用OPTIONS请求,可以通过自定义处理器包装器来实现。以下是一个示例,展示如何创建一个中间件来自动处理OPTIONS请求:
package main
import (
"net/http"
)
// 允许OPTIONS请求的中间件
func allowOptions(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 如果是OPTIONS请求,直接返回200状态码并设置CORS头部
if r.Method == http.MethodOptions {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusOK)
return
}
// 否则调用下一个处理器
next.ServeHTTP(w, r)
})
}
func main() {
// 创建路由器
mux := http.NewServeMux()
// 注册路由
mux.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
w.Write([]byte("POST请求成功"))
} else {
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
}
})
// 使用中间件包装路由器
handler := allowOptions(mux)
// 启动服务器
http.ListenAndServe(":8080", handler)
}
这个中间件会拦截所有请求,如果是OPTIONS请求,则直接返回200状态码并设置必要的CORS头部。对于其他请求,会正常传递给后续的处理器。
如果需要更细粒度的控制,可以在每个路由处理器中显式处理OPTIONS请求:
func apiHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodOptions:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusOK)
case http.MethodPost:
w.Write([]byte("POST请求成功"))
default:
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
}
}
这两种方法都可以在不使用第三方库的情况下全局处理OPTIONS请求。第一种方法通过中间件实现更简洁的全局处理,第二种方法提供了更细粒度的控制。

