Golang中正确设置CORS的流程指南

Golang中正确设置CORS的流程指南 你好!我正在尝试使用 http 包测试 CORS。我希望仅允许 localhost:8081 拥有 GET 访问权限(我的 Go 服务器在 localhost:8080 上)。通过发送 GET 请求,我可以从 localhost:8081 正常访问端点。但我仍然可以通过发送 POST 请求来访问它。我想这说得通,因为在处理程序中,我最终给出了“You got access!”的响应。但这是否意味着我需要显式检查请求的方法,如果它不是 GET 或 OPTIONS 就拒绝它?这样做对吗?

package main

import "net/http"

func main() {
    http.HandleFunc("/", reqHandler)
    http.ListenAndServe(":8080", nil)
}

func reqHandler(w http.ResponseWriter, r *http.Request) {
    // allow requests from localhost:8081
    w.Header().Add("Access-Control-Allow-Origin", "http://localhost:8081")

    // only allow get method
    w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")

    w.Write([]byte("You got access!"))
}

更多关于Golang中正确设置CORS的流程指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

非常感谢!中间件选项非常有用。

更多关于Golang中正确设置CORS的流程指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


谢谢,这看起来与我习惯的 Node.js 中的 Express 类似。我会探索这个选项,也会考虑直接使用标准库。

一种好的方法是使用 gorilla/mux 工具包,并在中间件中设置 CORS 头部。请参考以下示例。

	api.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			log.Println(r.RemoteAddr, r.Method, r.RequestURI)
			// open api need CORS
			enableCORS(w)
			if r.Method == "OPTIONS" {
				return
			}
			next.ServeHTTP(w, r)
		})
	})

但是,这是否意味着我需要显式检查请求的方法,如果它不是 GET 或 OPTIONS 就拒绝它?

是的,例如仅使用标准库:

func reqHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)

		return
    }

   ...
}

对于 CORS 头部,你可以将它们定义在一个中间件中,该中间件将用于每个请求,例如:

func corsMiddleware(h http.Handler) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        w.Header().Add("Access-Control-Allow-Origin", "http://localhost:8081")
        w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")

		h.ServeHTTP(w, r)
	}
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", reqHandler)
    http.ListenAndServe(":8080", corsMiddleware(mux))
}

你需要在处理程序中显式检查请求方法。CORS 头部本身不会阻止非 GET 请求,它们只是告诉浏览器哪些跨域请求是被允许的。对于实际的请求处理,你需要验证方法。

以下是修改后的代码:

package main

import "net/http"

func main() {
    http.HandleFunc("/", reqHandler)
    http.ListenAndServe(":8080", nil)
}

func reqHandler(w http.ResponseWriter, r *http.Request) {
    // 设置 CORS 头部
    w.Header().Set("Access-Control-Allow-Origin", "http://localhost:8081")
    w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
    
    // 处理预检请求
    if r.Method == "OPTIONS" {
        w.WriteHeader(http.StatusOK)
        return
    }
    
    // 只允许 GET 请求
    if r.Method != "GET" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    w.Write([]byte("You got access!"))
}

对于更完整的 CORS 处理,可以考虑使用中间件模式:

package main

import (
    "net/http"
)

func corsMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "http://localhost:8081")
        w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
        
        if r.Method == "OPTIONS" {
            w.WriteHeader(http.StatusOK)
            return
        }
        
        next(w, r)
    }
}

func main() {
    http.HandleFunc("/", corsMiddleware(handler))
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    if r.Method != "GET" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    w.Write([]byte("You got access!"))
}

这样处理可以确保:

  1. OPTIONS 预检请求被正确处理
  2. 非 GET 请求返回 405 状态码
  3. CORS 头部在所有响应中正确设置
回到顶部