设置 HTTP 头

我试图在我的 Go 网络服务器中设置一个头部。我使用的是 gorilla/muxnet/http包。

我想设置 Access-Control-Allow-Origin: *允许跨域 AJAX。

下面是我的围棋代码:

func saveHandler(w http.ResponseWriter, r *http.Request) {
// do some stuff with the request data
}


func main() {
r := mux.NewRouter()
r.HandleFunc("/save", saveHandler)
http.Handle("/", r)
http.ListenAndServe(":"+port, nil)
}

net/http包中有描述发送 http 请求头的文档,就好像它是一个客户机-我不确定如何设置响应头?

145132 次浏览

没关系,我弄明白了-我在 Header()上使用了 Set()方法(哦!)

我的联络人现在是这个样子:

func saveHandler(w http.ResponseWriter, r *http.Request) {
// allow cross domain AJAX requests
w.Header().Set("Access-Control-Allow-Origin", "*")
}

也许这能帮助像我这样缺乏咖啡因的人:)

我为这种情况创建包装:

func addDefaultHeaders(fn http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
fn(w, r)
}
}

不要使用’*’来源,直到您真的需要一个完全公开的行为。
作为 维基百科说:

“值”* 的特殊之处在于它不允许请求提供凭据, 意味着 HTTP 认证、客户端 SSL 证书,也不允许 cookie 将被送出”

这意味着,你会得到很多错误,尤其是在 Chrome 中,当你试图实现一个简单的身份验证时。

下面是一个更正过的包装:

// Code has not been tested.
func addDefaultHeaders(fn http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if origin := r.Header.Get("Origin"); origin != "" {
w.Header().Set("Access-Control-Allow-Origin", origin)
}
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
w.Header().Set("Access-Control-Allow-Credentials", "true")
fn(w, r)
}
}

不要忘记回复所有这些标题的飞行前选择的要求。

以上所有的答案都是错误的,因为它们不能处理 OPTION 的飞行前请求,解决方案是覆盖多路由器的接口。参见 AngularJS $http 获取请求失败,自定义头(CORS 中允许)

func main() {
r := mux.NewRouter()
r.HandleFunc("/save", saveHandler)
http.Handle("/", &MyServer{r})
http.ListenAndServe(":8080", nil);


}


type MyServer struct {
r *mux.Router
}


func (s *MyServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if origin := req.Header.Get("Origin"); origin != "" {
rw.Header().Set("Access-Control-Allow-Origin", origin)
rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
rw.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
// Stop here if its Preflighted OPTIONS request
if req.Method == "OPTIONS" {
return
}
// Lets Gorilla work
s.r.ServeHTTP(rw, req)
}

如果您不想覆盖您的路由器 (如果您的应用程序没有以支持此功能的方式进行配置,或者希望按路由配置 CORS) ,请添加一个 OPTION 处理程序来处理飞行前请求。

也就是说,你的路线看起来像:

accounts := router.Path("/accounts").Subrouter()
accounts.Methods("POST").Handler(AccountsCreate)
accounts.Methods("OPTIONS").Handler(AccountsCreatePreFlight)

请注意,除了我们的 POST 处理程序之外,还有 我们正在定义一个特定的 OPTION 方法处理程序

然后,为了实际处理 OPTION 预飞行方法,您可以像这样定义 AccountsCreatePreFlight:

// Check the origin is valid.
origin := r.Header.Get("Origin")
validOrigin, err := validateOrigin(origin)
if err != nil {
return err
}


// If it is, allow CORS.
if validOrigin {
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Methods", "POST")
w.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

除了了解 CORS 是如何工作的之外,真正让我感兴趣的是 飞行前请求的 HTTP 方法不同于实际请求的 HTTP 方法。为了启动 CORS,浏览器发送一个带有 HTTP Method OPTION 的起飞前请求,你必须在路由器中明确地处理这个请求,然后,如果它从你的应用程序收到适当的响应 "Access-Control-Allow-Origin": origin(或者“ *”) ,它就启动实际的请求。

我还相信您只能对标准类型的请求(即: GET)执行“ *”,但是对于其他请求,您必须像上面那样显式地设置原点。

我知道这是一个不同的回答,但这不是一个更关心的网络服务器吗?例如,Nginx可能会有所帮助。

Http _ headers _ module模块允许向响应头中添加“ Exires”和“ Cache-Control”头字段以及任意字段

...


location ~ ^<REGXP MATCHING CORS ROUTES> {
add_header Access-Control-Allow-Methods POST
...
}
...

在生产过程中,将 Nginx添加到您的 Go 服务前面似乎是明智的。它提供了更多用于授权、记录和修改请求的特性。此外,它还提供了控制谁可以访问您的服务的能力,不仅如此,还可以为应用程序中的特定位置指定不同的行为,如上所示。

我可以继续讨论为什么要使用 web 服务器和你的 goapi,但我认为这是另一个讨论的话题。

我有同样的问题,上述给出的解决方案是正确的,设置我有如下 1)客户的 Angularjs 2)围棋伺服器的 Beego 架构

请注意以下几点 1) CORS 设置只能在 GO 服务器上启用 2)除此之外,不要在 angularJS 中添加任何类型的头文件

.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}])

在你的 GO 服务器中,在请求开始被处理之前添加 CORS 设置,这样飞行前请求就会收到200 OK,然后 OPTION 方法就会被转换成 GET、 POST、 PUT 或者任何你的请求类型。

设置一个合适的 golang 中间件,这样您就可以在任何端点上重用它。

辅助人员类别及职能

type Adapter func(http.Handler) http.Handler
// Adapt h with all specified adapters.
func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
for _, adapter := range adapters {
h = adapter(h)
}
return h
}

真正的中间件

func EnableCORS() Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {


if origin := r.Header.Get("Origin"); origin != "" {
w.Header().Set("Access-Control-Allow-Origin", origin)
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, X-CSRF-Token, Authorization")
}
// Stop here if its Preflighted OPTIONS request
if r.Method == "OPTIONS" {
return
}
h.ServeHTTP(w, r)
})
}
}

终点

记住! 中间件以相反的顺序应用(ExpectGET ()首先触发)

mux.Handle("/watcher/{action}/{device}",Adapt(api.SerialHandler(mux),
api.EnableCORS(),
api.ExpectGET(),
))