美文网首页
Golang HTTP Request Header 分析

Golang HTTP Request Header 分析

作者: 七秒钟回忆待续 | 来源:发表于2021-06-16 16:52 被阅读0次

协议

https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2

Just as in HTTP/1.x, header field names are strings of ASCII characters that are compared in a case-insensitive fashion. However, header field names MUST be converted to lowercase prior to their encoding in HTTP/2. A request or response containing uppercase header field names MUST be treated as malformed.

大体就是:1.X版本 header 是大小写不敏感的,2版本的 header 必须要是编码为小写。

问题

其实这章节的疑惑点是请求头在进入到 Go 服务端后,大小写会被转换。例如: aB-cDE -> Ab-Cde 为啥会做类似如此奇怪的转换。

实现

直接看 Go 的处理。主逻辑函数在: go/src/net/textproto/reader.go:canonicalMIMEHeaderKey
主要的调用路径为:
serve->readRequest->readRequest->ReadMIMEHeader
emmm, 自己看代码理解。来测试一下,拷贝一下代码运行

func main() {
    fmt.Println(canonicalMIMEHeaderKey([]byte("aB-cDE")))
}
//输出:Ab-Cde

总结

了解这个有啥用呢?嗯,可以这样,然后那样...

漏点

貌似忘了 RPC 之间的 metadata 传递。context 之间的传递大小写问题。

Client

func main() {
    conn, err := grpc.Dial("localhost:8069", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("connect error %s", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)
    ctx := context.Background()
    ctx = metadata.AppendToOutgoingContext(ctx, "X-A-bC-De", "ok")
    reply, err := c.SayHi(ctx, &pb.GreetRequest{Name: "CTMD"})
    if err != nil {
        log.Fatalf("say hi error %s", err)
    }
    log.Printf("greet %v", reply)
}

Server

func (*server) SayHi(ctx context.Context, in *pb.GreetRequest) (*pb.GreetResponse, error) {
    md, ok := metadata.FromIncomingContext(ctx)
    fmt.Printf("got ctx %#v %t", md, ok)
    return &pb.GreetResponse{Message: "Hi " + in.Name}, nil
}

运行结果

服务端的输出:
got ctx metadata.MD{":authority":[]string{"localhost:8069"}, "content-type":[]string{"application/grpc"}, "user-agent":[]string{"grpc-go/1.36.0"}, "x-a-bc-de":[]string{"ok"}} true

嗯,确实符合协议标准....

但是

获取 header/meatadata 有啥注意的呢?

// go/src/net/http/header.go
func (h Header) Get(key string) string {
    return textproto.MIMEHeader(h).Get(key)
}
// google.golang.org/grpc@v1.36.0/metadata/metadata.go
func (md MD) Get(k string) []string {
    k = strings.ToLower(k)
    return md[k]
}

好像也没啥注意的,客户端会帮你处理这些小细节...

gRPC metadata 的处理大逻辑在 google.golang.org/grpc@v1.36.0/internal/transport/http2_client.go:createHeaderFields

相关文章

网友评论

      本文标题:Golang HTTP Request Header 分析

      本文链接:https://www.haomeiwen.com/subject/bjcfyltx.html