• 允许跨域访问
    • CORS对象
    • 默认CORSOptions
    • 使用示例

    允许跨域访问

    允许接口跨域往往是需要结合事件回调一起使用,来统一设置某些路由规则下的接口可以跨域访问。同时,针对允许WebSocket的跨域请求访问,也是通过该方式来实现。

    相关方法:https://godoc.org/github.com/gogf/gf/g/net/ghttp#Response

    1. // 默认的CORS配置
    2. func (r *Response) DefaultCORSOptions() CORSOptions
    3. // See https://www.w3.org/TR/cors/ .
    4. // 允许请求跨域访问.
    5. func (r *Response) CORS(options CORSOptions)
    6. // 允许请求跨域访问(使用默认配置).
    7. func (r *Response) CORSDefault()

    CORS对象

    CORSW3互联网标准组织对HTTP跨域请求的标准,在ghttp模块中,我们可以通过CORSOptions对象来管理对应的跨域请求选项。定义如下:

    1. // See https://www.w3.org/TR/cors/ .
    2. // 服务端允许跨域请求选项
    3. type CORSOptions struct {
    4. AllowOrigin string // Access-Control-Allow-Origin
    5. AllowCredentials string // Access-Control-Allow-Credentials
    6. ExposeHeaders string // Access-Control-Expose-Headers
    7. MaxAge int // Access-Control-Max-Age
    8. AllowMethods string // Access-Control-Allow-Methods
    9. AllowHeaders string // Access-Control-Allow-Headers
    10. }

    具体参数的介绍请查看W3组织官网手册。

    默认CORSOptions

    当然,为方便跨域设置,在ghttp模块中也提供了默认的跨域请求选项,通过ghttp.Response.DefaultCORSOptions获取。

    1. // 默认的CORS配置
    2. func (r *Response) DefaultCORSOptions() CORSOptions {
    3. return CORSOptions {
    4. AllowOrigin : gstr.TrimRight(r.request.Referer(), "/"),
    5. AllowMethods : HTTP_METHODS,
    6. AllowCredentials : "true",
    7. MaxAge : 3628800,
    8. }
    9. }

    大多数情况下,我们在需要允许跨域请求的接口中(一般情况下使用HOOK)可以直接使用CORSDefault()允许该接口跨域访问。

    使用示例

    我们来看一个简单的REST接口示例:

    1. package main
    2. import (
    3. "github.com/gogf/gf/g"
    4. "github.com/gogf/gf/g/net/ghttp"
    5. )
    6. type Order struct {
    7. }
    8. func (order *Order) Get(r *ghttp.Request) {
    9. r.Response.Write("GET")
    10. }
    11. func main() {
    12. s := g.Server()
    13. s.BindObjectRest("/api.v1/{.struct}", new(Order))
    14. s.SetPort(8199)
    15. s.Run()
    16. }

    接口地址是http://localhost/api.v1/order,当然这个接口是不允许跨域的。我们打开一个不同的域名,例如:百度首页(正好用了jQuery,方便调试),然后按F12打开开发者面板,在console下执行以下AJAX请求:

    1. $.get("http://localhost:8199/api.v1/order", function(result){
    2. console.log(result)
    3. });

    结果如下:允许跨域请求 - 图1返回了不允许跨域请求的提示错误,接着我们修改一下服务端接口的测试代码,如下:

    1. package main
    2. import (
    3. "github.com/gogf/gf/g"
    4. "github.com/gogf/gf/g/net/ghttp"
    5. )
    6. type Order struct{}
    7. func (order *Order) Get(r *ghttp.Request) {
    8. r.Response.Write("GET")
    9. }
    10. func main() {
    11. s := g.Server()
    12. s.BindHookHandlerByMap("/api.v1/*any", map[string]ghttp.HandlerFunc{
    13. "BeforeServe": func(r *ghttp.Request) {
    14. r.Response.CORSDefault()
    15. },
    16. })
    17. s.BindObjectRest("/api.v1/{.struct}", new(Order))
    18. s.SetPort(8199)
    19. s.Run()
    20. }

    我们增加了针对于路由/api.v1/*any的绑定事件BeforeServe,该事件将会在所有服务执行之前调用,该事件的回调方法中,我们通过调用CORSDefault方法使用默认的跨域设置允许跨域请求。该绑定的事件路由规则使用了模糊匹配规则,表示所有/api.v1开头的接口地址都允许跨域请求。

    返回刚才的百度首页,再次执行请求AJAX请求,这次便成功了:允许跨域请求 - 图2

    当然我们也可以通过CORSOptions对象以及CORS方法对跨域请求做更多的设置。