http跨域时的options请求详解及解决Go Rest Api 服务跨域问题

什么是options请求

无论后端还是前端,开发过程中多多少少都会碰到跨域问题,跨域问题中多数会遇到options请求问题。
在正式的跨域之前,某些条件下浏览器会根据需要发起一次预检,这就是options请求,用来让服务端返回允许的方法。

跨域请求类型

浏览器将跨域请求分为两类,简单请求和非简单请求,简单请求时浏览器不会进行预检,非简单请求时会进行预检。

简单请求

同时满足以下三个条件的属于简单请求:
1. 请求方式只能是: GET、POST、HEAD
2. HTTP请求头限制这几种字段:Accept、Accept-Language、Content-Language、Content-Type、Last-Event-ID
3. Content-type只能取:application/x-www-form-urlencoded、multipart/form-data、text/plain
简单请求,浏览器直接请求,在请求头信息中,增减origin字段,来说明本次请求来源(协议+域名+端口)。
服务器根据这个值来决定是否同意请求,服务器返回的响应则会多几个头信息端。

非简单请求

是对服务器有特殊要求的请求,比如请求方式是PUT/DELETE,或者Content-Type字段类型是application/json.
都会在正式通信之前,通过增加一次HTTP请求预检。向服务器询问当前网页所在域名是否在服务器许可名单,
服务器允许后方可进行后续正式请求,否则报错。这时需要后端实现拦截器排除Options请求。

Golang Restful 跨域

使用Go-Swagger生成的RESTFul后端框架中碰到了跨域Options预检请求问题,通过后端实现拦截器来过滤Options请求。
具体实现如下:
configure_XXX.go文件中实现以下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    func setupGlobalMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//cros
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers","Content-Type,AccessToken,X-CSRF-Token,Authorization,Token")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
w.Header().Set("Access-Control-Allow-Credentials","true")
method := r.Method
if method == "OPTIONS" {
w.WriteHeader(http.StatusNoContent)
return
}
//end
handler.ServeHTTP(w, r)
})
}