关于go-zero跨域自定义header的问题

场景说明:

在前后端分离的开发中,前端是单独部署的,可能是一个www.aaa.com的域名,而用go-zero的后端程序,可能部署在了www.bbb.com,这种方式在处理用户登陆的时候,基本上用的是jwt,用到jwt 基本上就要用到自定义header 的问题,比如header 里面可能会传Authorization这样的header头,但是Authorization这个又不是标准的响应头具体可以参考:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

然后看了一下官方的关于跨域的请求方式

package rest

import "net/http"

const (
    allowOrigin  = "Access-Control-Allow-Origin"
    allOrigins   = "*"
    allowMethods = "Access-Control-Allow-Methods"
    allowHeaders = "Access-Control-Allow-Headers"
    headers      = "Content-Type, Content-Length, Origin"
    methods      = "GET, HEAD, POST, PATCH, PUT, DELETE"
)

// CorsHandler handles cross domain OPTIONS requests.
// At most one origin can be specified, other origins are ignored if given.
func CorsHandler(origins ...string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if len(origins) > 0 {
            w.Header().Set(allowOrigin, origins[0])
        } else {
            w.Header().Set(allowOrigin, allOrigins)
        }
        w.Header().Set(allowMethods, methods)
        w.Header().Set(allowHeaders, headers)
        w.WriteHeader(http.StatusNoContent)
    })
}

这个写得很简单,属于 简单跨域请求,满足不了,

前后端分离的复杂跨域请求(因为是要做自定义header)

然后我自己写他一个小例子

package main

import (
    "net/http"
    "fmt"
)

func main() {
    http.HandleFunc("/votes/enroll/lists", TestCrossOrigin)
    http.ListenAndServe(":8001", nil)
}

func TestCrossOrigin(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin","http://localhost:8084")
    w.Header().Add("Access-Control-Allow-Headers","Content-Type,Token")
    w.Header().Set("Access-Control-Allow-Credentials","true")
    fmt.Fprintln(w,"hello cros!")
}

启动服务

➜  src go run main.go

客户端是用uniapp写的:

uni.request({
            header:{
                'authorization':"ok!!!!",
                'beid':1,
                'ptyid':2,
                'authorization':'2323',
                
            },
           //withCredentials:true,
          // url: this.$host + 'api/news',
          url: 'http://localhost:8001/votes/enroll/lists?act,
          //url: 'http://localhost:8887/votes/enroll/lists?act,
          //url: 'http://www.aaa.com/votes/enroll/lists?act,
              
          data: this.requestParams,
          success: (result) => {
              console.log(result);
            }
})

各种试都能成功,显示 不域名

但是换成go-zero的,我改了一下handlers.go的内容

package rest

import "net/http"

const (
    allowOrigin  = "Access-Control-Allow-Origin"
    allOrigins   = "*"
    allowMethods = "Access-Control-Allow-Methods"
    allowHeaders = "Access-Control-Allow-Headers"
    headers      = "Content-Type, Content-Length, Origin"
    methods      = "GET, HEAD, POST, PATCH, PUT, DELETE"
)

// CorsHandler handles cross domain OPTIONS requests.
// At most one origin can be specified, other origins are ignored if given.
func CorsHandler(origins ...string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin","http://localhost:8084")
        w.Header().Add("Access-Control-Allow-Headers","Content-Type,Token")
        w.Header().Set("Access-Control-Allow-Credentials","true")
w.Write([]byte("ok"))

     w.WriteHeader(http.StatusOK)

    })
}

写成一模一样都不行,于是我抓包分析

go-zero改的抓包

Frame 9483: 824 bytes on wire (6592 bits), 824 bytes captured (6592 bits) on interface lo0, id 0

Null/Loopback

Internet Protocol Version 6, Src: ::1, Dst: ::1

Transmission Control Protocol, Src Port: 59159, Dst Port: 8887, Seq: 1, Ack: 1, Len: 748

Hypertext Transfer Protocol

OPTIONS /votes/enroll/lists?actid=1&keyword=5&columnId=0&minId=0&pageSize=10&column=id%2Cpost_id%2Ctitle%2Cauthor_name%2Ccover%2Cpublished_at%2Ccomments_count&time=1611816221697 HTTP/1.1\r\n

Host: localhost:8887\r\n

Connection: keep-alive\r\n

Pragma: no-cache\r\n

Cache-Control: no-cache\r\n

Accept: */*\r\n

Access-Control-Request-Method: GET\r\n

Access-Control-Request-Headers: authorization,beid,ptyid\r\n

Origin: http://localhost:8085\r\n

User-Agent: Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36\r\n

Sec-Fetch-Mode: cors\r\n

Sec-Fetch-Site: same-site\r\n

Sec-Fetch-Dest: empty\r\n

Referer: http://localhost:8085/\r\n

Accept-Encoding: gzip, deflate, br\r\n

Accept-Language: zh-CN,zh;q=0.9\r\n

\r\n

[Full request URI: http://localhost:8887/votes/enroll/lists?actid=1&keyword=5&columnId=0&minId=0&pageSize=10&column=id%2Cpost_id%2Ctitle%2Cauthor_name%2Ccover%2Cpublished_at%2Ccomments_count&time=1611816221697]

[HTTP request 1/1]

[Response in frame: 9485]

Frame 5624: 336 bytes on wire (2688 bits), 336 bytes captured (2688 bits) on interface lo0, id 0

Null/Loopback

Internet Protocol Version 6, Src: ::1, Dst: ::1

Transmission Control Protocol, Src Port: 8887, Dst Port: 59159, Seq: 2, Ack: 749, Len: 260

Hypertext Transfer Protocol

HTTP/1.1 200 OK\r\n

Access-Control-Allow-Credentials: true\r\n

Access-Control-Allow-Headers: Content-Type,Token\r\n

Access-Control-Allow-Origin: http://localhost:8084\r\n

Date: Thu, 28 Jan 2021 06:41:42 GMT\r\n

Content-Length: 2\r\n

Content-Type: text/plain; charset=utf-8\r\n

\r\n

[HTTP response 1/1]

[Time since request: 0.007791000 seconds]

[Request in frame: 5606]

[Request URI: http://localhost:8887/votes/enroll/lists?actid=1&keyword=5&columnId=0&minId=0&pageSize=10&column=id%2Cpost_id%2Ctitle%2Cauthor_name%2Ccover%2Cpublished_at%2Ccomments_count&time=1611816102966]

File Data: 2 bytes

Line-based text data: text/plain (1 lines)


自己写的

Frame 7369: 824 bytes on wire (6592 bits), 824 bytes captured (6592 bits) on interface lo0, id 0

Null/Loopback

Internet Protocol Version 6, Src: ::1, Dst: ::1

Transmission Control Protocol, Src Port: 63167, Dst Port: 8001, Seq: 1, Ack: 1, Len: 748

Hypertext Transfer Protocol

OPTIONS /votes/enroll/lists?actid=1&keyword=5&columnId=0&minId=0&pageSize=10&column=id%2Cpost_id%2Ctitle%2Cauthor_name%2Ccover%2Cpublished_at%2Ccomments_count&time=1611816281059 HTTP/1.1\r\n

Host: localhost:8001\r\n

Connection: keep-alive\r\n

Pragma: no-cache\r\n

Cache-Control: no-cache\r\n

Accept: */*\r\n

Access-Control-Request-Method: GET\r\n

Access-Control-Request-Headers: authorization,beid,ptyid\r\n

Origin: http://localhost:8085\r\n

User-Agent: Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36\r\n

Sec-Fetch-Mode: cors\r\n

Sec-Fetch-Site: same-site\r\n

Sec-Fetch-Dest: empty\r\n

Referer: http://localhost:8085/\r\n

Accept-Encoding: gzip, deflate, br\r\n

Accept-Language: zh-CN,zh;q=0.9\r\n

\r\n

[Full request URI: http://localhost:8001/votes/enroll/lists?actid=1&keyword=5&columnId=0&minId=0&pageSize=10&column=id%2Cpost_id%2Ctitle%2Cauthor_name%2Ccover%2Cpublished_at%2Ccomments_count&time=1611816281059]

[HTTP request 1/2]

[Response in frame: 7371]

[Next request in frame: 7383]


Frame 515: 352 bytes on wire (2816 bits), 352 bytes captured (2816 bits) on interface lo0, id 0

Null/Loopback

Internet Protocol Version 6, Src: ::1, Dst: ::1

Transmission Control Protocol, Src Port: 8001, Dst Port: 58202, Seq: 1, Ack: 749, Len: 276

Hypertext Transfer Protocol

HTTP/1.1 200 OK\r\n

Access-Control-Allow-Credentials: true\r\n

Access-Control-Allow-Headers: Content-Type,Token,authorization,beid,ptyid\r\n

Access-Control-Allow-Origin: *\r\n

Date: Thu, 28 Jan 2021 06:14:17 GMT\r\n

Content-Length: 12\r\n

Content-Type: text/plain; charset=utf-8\r\n

\r\n

[HTTP response 1/2]

[Time since request: 0.000118000 seconds]

[Request in frame: 513]

[Next request in frame: 517]

[Next response in frame: 519]

[Request URI: http://localhost:8001/votes/enroll/lists?actid=1&keyword=5&columnId=0&minId=0&pageSize=10&column=id%2Cpost_id%2Ctitle%2Cauthor_name%2Ccover%2Cpublished_at%2Ccomments_count&time=1611814457976]

File Data: 12 bytes

Line-based text data: text/plain (1 lines)

几乎差不多,真的搞不懂了,后面,实在没有bugs ,直接改的nginx

server {
    listen       80;
    server_name  www.aaa.com;

    location / {
        proxy_connect_timeout 1000;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host            $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";

    if ($request_method = 'OPTIONS') {
            add_header Cache-Control private;
            add_header 'Access-Control-Allow-Origin' '*';
               add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Max-Age' 86400;
            add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Token,DNT,Content-Type,Cache-Control,User-Agent,Keep-Alive,Authorization,authorization,beid,ptyid';
        return 204;
    }
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,token';


        proxy_pass http://http_ss_soholly;
    }
}
upstream http_ss_soholly {
    server 172.29.4.251:8887;
    keepalive 256;

算还是把问题解决了