获取 RAW header 的 http 响应

Get RAW header of http response

如何像这样将原始 header 响应作为字符串:

alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"
cache-control: private, max-age=0
content-encoding: br
content-type: text/html; charset=UTF-8
date: Tue, 08 Jan 2019 06:19:47 GMT
expires: -1
server: gws
set-cookie: 1P_JAR=2019-01-08-06; expires=Thu, 07-Feb-2019 06:19:47 GMT; path=/; domain=.google.com
set-cookie: SIDCC=ABtHo-HHNcja-cEEFEUXtBmLOdql4RTVMCWKGApEFFb8lWSAqaTF_fi0gDLoWaCzH3ogvEofah0; expires=Mon, 08-Apr-2019 06:19:47 GMT; path=/; domain=.google.com; priority=high
status: 200

因为我想从响应 header 中获取多个 set-cookie 值。 使用 Http.Response.Header.Get("set-cookies") 仅 return 最后一行。

或者如何获取多个cookie?

使用fmt.Printf("%+v", resp.Header)

可以将所有header写入如下字符串:

map[Set-Cookie:[CASPRIVACY=""; Path=/ CASTGC=TGT-1248283-0BRja0uNQR9PntBl4HnrzKA44q5XDQXxA5FRVcnO9Xn6CkTU6S-passport; Path=/ CASLOGC=%7B%22myuniRole%22%3A0%2C%22username%22%3A%22a6051b9d08384f3ea2d203e744d3f7e6%22%2C%22mycuRole%22%3A0%2C%22userId%22%3A192676671%2C%22myinstRole%22%3A0%2C%22realName%22%3A%22%E9%9B%B7%E7%BA%A2%E6%A2%85%22%2C%22uuid%22%3A%22V4eoYpNB%22%2C%22headPic%22%3A%22http%3A%2F%2Fimage.xxx.com%2Fzhs%2Fapp%2Fcontent%2F201812%2Ff0b20d740df04d3196a20bc39f58ab56_s3.png%22%7D; Domain=.xxxx.com; Path=/ SERVERID=958b97eacbe3c49360ace2dfc0bd31b4|1546915535|1546915533;Path=/] Pragma:[no-cache] Expires:[Thu, 01 Jan 1970 00:00:00 GMT] Cache-Control:[no-cache no-store] Location:[http://online.xxx.com/onlineSchool/?ticket=ST-3285248-UiTbNt7bnUwXdtWSznIT-passport.xxxx.com] Date:[Tue, 08 Jan 2019 02:45:35 GMT] Content-Length:[0] Connection:[keep-alive]]

很难通过使用 split 和 regx 从字符串中获取所有 cookie

标准 http 库默认解析 header。
使用 fasthttp(您需要 re-write 您的路由器和处理程序功能)将使您能够获得原始 header.

如果你想要 raw headers,你需要为 net.Conn 编写一些包装器来捕获原始 header在它被 http 库解释之前。

但您似乎并不真的需要原始的 header——甚至根本不需要完整的 header。如果您的目标只是读取多个 cookie,最简单的方法是在响应中使用 Cookies 方法。

这两者之间的中间选项是读取响应的整个 Header 字段。这将呈现 full header,但不能保证其顺序,并且将完成最少的解析(删除换行符等),所以不能说这真是 "raw"。但是,如果 header 重复,它会通过将所有 header 值存储在 []string 中来保留多个值。因此,就这个问题而言,这应该是完全足够的(尽管 Response.Cookies,如上所述,会更容易)。

在我看来,往返响应的最佳选择是 httputil#DumpResponse:

package raw

import (
   "bufio"
   "bytes"
   "net/http"
   "net/http/httputil"
)

func encode(res *http.Response) ([]byte, error) {
   return httputil.DumpResponse(res, false)
}

func decode(data []byte) (*http.Response, error) {
   return http.ReadResponse(bufio.NewReader(bytes.NewReader(data)), nil)
}

或者,如果您只想要 cookie,您可以这样做:

package raw

import (
   "encoding/json"
   "net/http"
)

func encode(res *http.Response) ([]byte, error) {
   return json.Marshal(res.Cookies())
}

func decode(data []byte) ([]http.Cookie, error) {
   var c []http.Cookie
   if e := json.Unmarshal(data, &c); e != nil {
      return nil, e
   }
   return c, nil
}

或者对于单个 cookie:

package raw

import (
   "encoding/json"
   "net/http"
)

func encode(res *http.Response, name string) ([]byte, error) {
   for _, c := range res.Cookies() {
      if c.Name == name {
         return json.Marshal(c)
      }
   }
   return nil, http.ErrNoCookie
}

func decode(data []byte) (*http.Cookie, error) {
   c := new(http.Cookie)
   if e := json.Unmarshal(data, c); e != nil {
      return nil, e
   }
   return c, nil
}

https://golang.org/pkg/net/http/httputil#DumpResponse