Golang HTTP Request Header 分析

協(xié)議

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 必須要是編碼為小寫。

問題

其實這章節(jié)的疑惑點是請求頭在進(jìn)入到 Go 服務(wù)端后,大小寫會被轉(zhuǎn)換。例如: aB-cDE -> Ab-Cde 為啥會做類似如此奇怪的轉(zhuǎn)換。

實現(xiàn)

直接看 Go 的處理。主邏輯函數(shù)在: go/src/net/textproto/reader.go:canonicalMIMEHeaderKey
主要的調(diào)用路徑為:
serve->readRequest->readRequest->ReadMIMEHeader
emmm, 自己看代碼理解。來測試一下,拷貝一下代碼運行

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

總結(jié)

了解這個有啥用呢?嗯,可以這樣,然后那樣...

漏點

貌似忘了 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
}

運行結(jié)果

服務(wù)端的輸出:
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

嗯,確實符合協(xié)議標(biāo)準(zhǔn)....

但是

獲取 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]
}

好像也沒啥注意的,客戶端會幫你處理這些小細(xì)節(jié)...

gRPC metadata 的處理大邏輯在 google.golang.org/grpc@v1.36.0/internal/transport/http2_client.go:createHeaderFields

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容