Source file src/vendor/golang.org/x/net/internal/http3/qpack_encode.go
1 // Copyright 2025 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package http3 6 7 import ( 8 "golang.org/x/net/internal/httpcommon" 9 ) 10 11 type qpackEncoder struct { 12 // The encoder has no state for now, 13 // but that'll change once we add dynamic table support. 14 // 15 // TODO: dynamic table support. 16 } 17 18 func (qe *qpackEncoder) init() { 19 staticTableOnce.Do(initStaticTableMaps) 20 } 21 22 // encode encodes a list of headers into a QPACK encoded field section. 23 // 24 // The headers func must produce the same headers on repeated calls, 25 // although the order may vary. 26 func (qe *qpackEncoder) encode(headers func(func(itype indexType, name, value string))) []byte { 27 // Encoded Field Section prefix. 28 // 29 // We don't yet use the dynamic table, so both values here are zero. 30 var b []byte 31 b = appendPrefixedInt(b, 0, 8, 0) // Required Insert Count 32 b = appendPrefixedInt(b, 0, 7, 0) // Delta Base 33 34 headers(func(itype indexType, name, value string) { 35 // Technically, it is the responsibility of the protocol using HTTP/3 36 // to ensure that all field names are already in lowercase. However, 37 // this QPACK implementation is solely used by and live in the http3 38 // package. So, we might as well do the lowercasing here to make sure 39 // we do not miss any callsites or need to create yet another struct 40 // wrapping the qpackEncoder. 41 name, ascii := httpcommon.LowerHeader(name) 42 // Skip writing invalid headers. Per RFC 9114 section 4.2: "Field 43 // names are strings containing a subset of ASCII characters." 44 if !ascii { 45 return 46 } 47 if itype == mayIndex { 48 if i, ok := staticTableByNameValue[tableEntry{name, value}]; ok { 49 b = appendIndexedFieldLine(b, staticTable, i) 50 return 51 } 52 } 53 if i, ok := staticTableByName[name]; ok { 54 b = appendLiteralFieldLineWithNameReference(b, staticTable, itype, i, value) 55 } else { 56 b = appendLiteralFieldLineWithLiteralName(b, itype, name, value) 57 } 58 }) 59 60 return b 61 } 62