为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Golang 中获取 request.Header 的大小(以字节为单位)?

如何在 Golang 中获取 request.Header 的大小(以字节为单位)?

Go
慕桂英546537 2022-10-10 16:52:25
我需要找到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所以我们不必使用递归。
查看完整描述

1 回答

?
一只名叫tom的猫

TA贡献1906条经验 获得超3个赞

https://pkg.go.dev/net/http#Server.MaxHeaderBytes可以为您处理。

此演示在 Playground 中无法可靠运行(拨号或连接超时)。不过,它似乎在本地可靠地工作,这让我猜这是操场行为的产物。

我们将启动一个具有较低 MaxHeaderBytes 的 http Server,然后大大超过它。

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

如您所见,如果所有标题都太大,将自动生成 431。


如果特定标头太长,您的处理程序本身可能适合以 431 响应,但是当您的处理程序通过http.Request时,标头已被接收。尝试自己计算标头的总长度然后基于此以 431 响应是没有意义的。


此外,标准标题可能会来来去去,因此过于严格地限制整体标题大小是不明智的。


相反,请检查您关心的任何单个标题。


查看完整回答
反对 回复 2022-10-10
  • 1 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信