在Go中解码http2帧头/数据

I am trying to read from a tcp connection which contains HTTP/2 data. Below is the code for reading HEADERS frame -

framer := http2.NewFramer(conn, conn)
frame, _ := framer.ReadFrame()

fmt.Printf("fh type: %s
", frame.Header().Type)
fmt.Printf("fh type: %d
", frame.Header().Type)
fmt.Printf("fh flag: %d
", frame.Header().Flags)
fmt.Printf("fh length: %d
", frame.Header().Length)
fmt.Printf("fh streamid: %d
", frame.Header().StreamID)
headersframe := (frame1.(*http2.HeadersFrame))
fmt.Printf("stream ended? %v
", headersframe.StreamEnded())
fmt.Printf("block fragment: %x
", headersframe.HeaderBlockFragment())        

I send request using curl as -

curl -v https://127.0.0.1:8000/ -k --http2

This is the output I get (after reading connection preface and SETTINGS), if I read from the conn using above code -

fh type: HEADERS
fh type: 1
fh flag: 5
fh length: 30
fh streamid: 1
stream ended? true
block fragment: 828487418a089d5c0b8170dc6c4d8b7a8825b650c3abb6f2e053032a2f2a

I understand the ouput, except the block fragment part and how to decode it into ascii string? I want to know the protocol/method/url path information.

I figured it out using Go hpack library (https://godoc.org/golang.org/x/net/http2/hpack) -

decoder := hpack.NewDecoder(2048, nil)
hf, _ := decoder.DecodeFull(headersframe.HeaderBlockFragment())
for _, h := range hf {
      fmt.Printf("%s
", h.Name + ":" + h.Value)
}

This prints -

:method:GET
:path:/
:scheme:https
:authority:127.0.0.1:5252
user-agent:curl/7.58.0
accept:*/*

The "header block fragment" is encoded using HPACK.

Go has an implementation to encode and decode HPACK, so you don't have to write your own.

You can find here an example of using both the encoder and decoder Go API.