如何在 Golang 中获得 request.Header 字节的大小?
How can I get a size of request.Header in bytes in Golang?
我需要找到 request.Header
的大小,其中请求有 *http.Request
类型:
req, err := http.NewRequest("GET", "/", nil)
cookie := &http.Cookie{Name: "foo", Value: "bar"}
req.AddCookie(cookie)
我试过了
len(request.Header) # returned the number of elements in the map -- essentially the number of headers
和
for k, v := range req.Header {
bytesSize += len(k) + len(v)
}
这也不起作用,因为 v
是一张地图。
我找到了 个问题,但答案似乎很复杂(它们的映射值是整数,但这里不是这种情况)。
更新:实际上这里是 type Header map[string][]string
的定义,因此我们不必使用递归。
https://pkg.go.dev/net/http#Server.MaxHeaderBytes 可以为您处理。
此演示在 Playground 中无法可靠运行(拨号或连接超时)。不过,它似乎在本地可靠地工作,这让我猜想这是 playground 行为的产物。
我们将以低 MaxHeaderBytes 启动一个 http 服务器,然后大大超过它。
package main
import (
"context"
"fmt"
"io"
"net"
"net/http"
"strings"
"time"
)
func main() {
res := make(chan error)
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%+v", r.Header)
})
s := &http.Server{
Addr: "127.0.0.1:8103",
Handler: mux,
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
MaxHeaderBytes: 2048,
}
if l, err := net.Listen("tcp", "127.0.0.1:8103"); err != nil {
panic(fmt.Errorf("Couldn't listen: %w", err))
} else {
go func() {
res <- s.Serve(l)
}()
}
client := &http.Client{
Timeout: 3 * time.Second,
}
req, err := http.NewRequest("GET", "http://127.0.0.1:8103", nil)
if err != nil {
panic(err)
}
req.Header.Add("X-Long-Header", strings.Repeat("long ", 2048)+"header")
resp, err := client.Do(req)
if err != nil {
panic(fmt.Errorf("HTTP Request failed: %w", err))
}
fmt.Println(resp)
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(fmt.Errorf("Could not read response body: %w", err))
}
fmt.Println("Body:", string(body))
s.Shutdown(context.Background())
<-res
}
在这里,我将 MaxHeaderBytes
设置为一个相当小的值。我在 X-Long-Header: long long long .... header
中传递的值远远超过该值。如果您可以让 playground 工作(只需 运行 几次)或 运行 在本地工作,您将获得:
&{431 Request Header Fields Too Large 431 HTTP/1.1 1 1 map[Content-Type:[text/plain; charset=utf-8]] 0xc00001a180 -1 [] true false map[] 0xc000176000 <nil>}
Body: 431 Request Header Fields Too Large
如您所见,如果所有 header 都太大,将自动生成 431。
如果特定的 header 太长,您的处理程序本身用 431 响应可能是合适的,但是当您的处理程序被传递 http.Request
时,header 已收到。尝试自己计算 header 的总长度然后基于此返回 431 是没有意义的。
此外,标准 header 可能来来去去,因此将整体 header 大小限制得太紧是不明智的。
相反,请检查您关心的 header 个人。
我需要找到 request.Header
的大小,其中请求有 *http.Request
类型:
req, err := http.NewRequest("GET", "/", nil)
cookie := &http.Cookie{Name: "foo", Value: "bar"}
req.AddCookie(cookie)
我试过了
len(request.Header) # returned the number of elements in the map -- essentially the number of headers
和
for k, v := range req.Header {
bytesSize += len(k) + len(v)
}
这也不起作用,因为 v
是一张地图。
我找到了
更新:实际上这里是 type Header map[string][]string
的定义,因此我们不必使用递归。
https://pkg.go.dev/net/http#Server.MaxHeaderBytes 可以为您处理。
此演示在 Playground 中无法可靠运行(拨号或连接超时)。不过,它似乎在本地可靠地工作,这让我猜想这是 playground 行为的产物。
我们将以低 MaxHeaderBytes 启动一个 http 服务器,然后大大超过它。
package main
import (
"context"
"fmt"
"io"
"net"
"net/http"
"strings"
"time"
)
func main() {
res := make(chan error)
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%+v", r.Header)
})
s := &http.Server{
Addr: "127.0.0.1:8103",
Handler: mux,
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
MaxHeaderBytes: 2048,
}
if l, err := net.Listen("tcp", "127.0.0.1:8103"); err != nil {
panic(fmt.Errorf("Couldn't listen: %w", err))
} else {
go func() {
res <- s.Serve(l)
}()
}
client := &http.Client{
Timeout: 3 * time.Second,
}
req, err := http.NewRequest("GET", "http://127.0.0.1:8103", nil)
if err != nil {
panic(err)
}
req.Header.Add("X-Long-Header", strings.Repeat("long ", 2048)+"header")
resp, err := client.Do(req)
if err != nil {
panic(fmt.Errorf("HTTP Request failed: %w", err))
}
fmt.Println(resp)
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(fmt.Errorf("Could not read response body: %w", err))
}
fmt.Println("Body:", string(body))
s.Shutdown(context.Background())
<-res
}
在这里,我将 MaxHeaderBytes
设置为一个相当小的值。我在 X-Long-Header: long long long .... header
中传递的值远远超过该值。如果您可以让 playground 工作(只需 运行 几次)或 运行 在本地工作,您将获得:
&{431 Request Header Fields Too Large 431 HTTP/1.1 1 1 map[Content-Type:[text/plain; charset=utf-8]] 0xc00001a180 -1 [] true false map[] 0xc000176000 <nil>}
Body: 431 Request Header Fields Too Large
如您所见,如果所有 header 都太大,将自动生成 431。
如果特定的 header 太长,您的处理程序本身用 431 响应可能是合适的,但是当您的处理程序被传递 http.Request
时,header 已收到。尝试自己计算 header 的总长度然后基于此返回 431 是没有意义的。
此外,标准 header 可能来来去去,因此将整体 header 大小限制得太紧是不明智的。
相反,请检查您关心的 header 个人。