Iris服务端跨域

参考文章

Nginx配置跨域请求 Access-Control-Allow-Origin *
Nginx配置跨域访问
CORS跨域资源共享

CORS

CROS全称是跨域资源共享 (Cross-origin resource sharing),跨域资源共享(CORS)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的HTTP请求方法(特别是GET以外的HTTP请求,或者搭配某些MIME类型的POST请求),浏览器必须首先使用OPTIONS方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

问题和解决方法

服务端默认是不被允许跨域的,当浏览器跨域访问出现403跨域错误的时候No 'Access-Control-Allow-Origin' header is present on the requested resource。两种解决方法,使用Nginx作为反向代理服务器,对响应添加对应的头信息服务端自身实现,允许跨域。不管哪种方式都是添加响应头信息Access-Control-Allow-Origin *,表示服务端可以接受所有的请求源Origin,即接受所有跨域的请求。

服务端允许跨域

通过nginx作为反向代理服务器,解决跨域问题网上有很多教程,这里就不不累述了。主要描述下怎样在服务端自身实现跨域,这样是比较理想的解决方法,可以通过Iris cors 中间件实现,也可以自己代码实现。

Iris cors 中间件

实例代码可以参考文章 CORS跨域资源共享

代码实现

自定义middleware包新增函数Cors。给所有请求添加头信息Access-Control-Allow-Origin *,如果是OPTIONS方法的预请求,成功响应并添加对应的头信息,状态码响应204或者200。不设置状态码默认响应301,预请求响应失败会造成最后跨域访问失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package middleware

import (
"github.com/kataras/iris"
)

// Cors 实现服务端跨域
func Cors(ctx iris.Context) {
ctx.Header("Access-Control-Allow-Origin", "*")
if ctx.Request().Method == "OPTIONS" {
ctx.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS")
ctx.Header("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization")
ctx.StatusCode(204)
return
}
ctx.Next()
}

如果API接口没有实现OPTIONS方法,需要给所有接口设置缺省的OPTIONS方法,不然捕捉不到对应API接口的OPTIONS请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package routers

import (
"github.com/kataras/iris"
"github.com/kataras/iris/middleware/recover"
...
)

// InitRouter 路由初始化
func InitRouter() *iris.Application {
r := iris.New()
r.Use(recover.New())

...

// common
common := r.Party("/")
{
common.Options("*", func(ctx iris.Context) {
ctx.Next()
})
...
}

...

return r
}

然后在所有请求前面添加拦截器,使用自定义的中间件r.Use(cors)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package routers

import (
"github.com/kataras/iris"
"github.com/kataras/iris/middleware/recover"
"github.com/xiaomastack/hobby/middleware"
...
)

func cors(ctx iris.Context) {
middleware.Cors(ctx)
}

// InitRouter 路由初始化
func InitRouter() *iris.Application {
r := iris.New()
r.Use(recover.New())

// cors
r.Use(cors)
...

// common
common := r.Party("/")
{
common.Options("*", func(ctx iris.Context) {
ctx.Next()
})
...
}

...

return r
}

OPTIONS方法请求任一API接口,可以测试是否生效,如下返回的结果显示已生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ curl -X OPTIONS -vv http://localhost:8080/hs
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> OPTIONS /hs HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 204 No Content
< Access-Control-Allow-Headers: Content-Type, Accept, Authorization
< Access-Control-Allow-Methods: GET,POST,PUT,DELETE,PATCH,OPTIONS
< Access-Control-Allow-Origin: *
< Date: Tue, 17 Sep 2019 03:03:18 GMT
<
* Connection #0 to host localhost left intact
----------------本文结束 感谢阅读----------------