Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
7
vendor/github.com/quic-go/qpack/.codecov.yml
generated
vendored
Normal file
7
vendor/github.com/quic-go/qpack/.codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
coverage:
|
||||
round: nearest
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 1
|
||||
patch: false
|
||||
6
vendor/github.com/quic-go/qpack/.gitignore
generated
vendored
Normal file
6
vendor/github.com/quic-go/qpack/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
fuzzing/*.zip
|
||||
fuzzing/coverprofile
|
||||
fuzzing/crashers
|
||||
fuzzing/sonarprofile
|
||||
fuzzing/suppressions
|
||||
fuzzing/corpus/
|
||||
3
vendor/github.com/quic-go/qpack/.gitmodules
generated
vendored
Normal file
3
vendor/github.com/quic-go/qpack/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "integrationtests/interop/qifs"]
|
||||
path = integrationtests/interop/qifs
|
||||
url = https://github.com/qpackers/qifs.git
|
||||
27
vendor/github.com/quic-go/qpack/.golangci.yml
generated
vendored
Normal file
27
vendor/github.com/quic-go/qpack/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
run:
|
||||
linters-settings:
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- asciicheck
|
||||
- deadcode
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- goconst
|
||||
- gofmt # redundant, since gofmt *should* be a no-op after gofumpt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gosimple
|
||||
- ineffassign
|
||||
- misspell
|
||||
- prealloc
|
||||
- scopelint
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- structcheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- vet
|
||||
|
||||
7
vendor/github.com/quic-go/qpack/LICENSE.md
generated
vendored
Normal file
7
vendor/github.com/quic-go/qpack/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Copyright 2019 Marten Seemann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
20
vendor/github.com/quic-go/qpack/README.md
generated
vendored
Normal file
20
vendor/github.com/quic-go/qpack/README.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# QPACK
|
||||
|
||||
[](https://godoc.org/github.com/marten-seemann/qpack)
|
||||
[](https://codecov.io/gh/marten-seemann/qpack)
|
||||
|
||||
This is a minimal QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)) implementation in Go. It is minimal in the sense that it doesn't use the dynamic table at all, but just the static table and (Huffman encoded) string literals. Wherever possible, it reuses code from the [HPACK implementation in the Go standard library](https://github.com/golang/net/tree/master/http2/hpack).
|
||||
|
||||
It should be able to interoperate with other QPACK implemetations (both encoders and decoders), however it won't achieve a high compression efficiency.
|
||||
|
||||
## Running the interop tests
|
||||
|
||||
Install the [QPACK interop files](https://github.com/qpackers/qifs/) by running
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
Then run the tests:
|
||||
```bash
|
||||
ginkgo -r integrationtests
|
||||
```
|
||||
271
vendor/github.com/quic-go/qpack/decoder.go
generated
vendored
Normal file
271
vendor/github.com/quic-go/qpack/decoder.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
package qpack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
// A decodingError is something the spec defines as a decoding error.
|
||||
type decodingError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (de decodingError) Error() string {
|
||||
return fmt.Sprintf("decoding error: %v", de.err)
|
||||
}
|
||||
|
||||
// An invalidIndexError is returned when an encoder references a table
|
||||
// entry before the static table or after the end of the dynamic table.
|
||||
type invalidIndexError int
|
||||
|
||||
func (e invalidIndexError) Error() string {
|
||||
return fmt.Sprintf("invalid indexed representation index %d", int(e))
|
||||
}
|
||||
|
||||
var errNoDynamicTable = decodingError{errors.New("no dynamic table")}
|
||||
|
||||
// errNeedMore is an internal sentinel error value that means the
|
||||
// buffer is truncated and we need to read more data before we can
|
||||
// continue parsing.
|
||||
var errNeedMore = errors.New("need more data")
|
||||
|
||||
// A Decoder is the decoding context for incremental processing of
|
||||
// header blocks.
|
||||
type Decoder struct {
|
||||
mutex sync.Mutex
|
||||
|
||||
emitFunc func(f HeaderField)
|
||||
|
||||
readRequiredInsertCount bool
|
||||
readDeltaBase bool
|
||||
|
||||
// buf is the unparsed buffer. It's only written to
|
||||
// saveBuf if it was truncated in the middle of a header
|
||||
// block. Because it's usually not owned, we can only
|
||||
// process it under Write.
|
||||
buf []byte // not owned; only valid during Write
|
||||
|
||||
// saveBuf is previous data passed to Write which we weren't able
|
||||
// to fully parse before. Unlike buf, we own this data.
|
||||
saveBuf bytes.Buffer
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder
|
||||
// The emitFunc will be called for each valid field parsed,
|
||||
// in the same goroutine as calls to Write, before Write returns.
|
||||
func NewDecoder(emitFunc func(f HeaderField)) *Decoder {
|
||||
return &Decoder{emitFunc: emitFunc}
|
||||
}
|
||||
|
||||
func (d *Decoder) Write(p []byte) (int, error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
d.mutex.Lock()
|
||||
n, err := d.writeLocked(p)
|
||||
d.mutex.Unlock()
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (d *Decoder) writeLocked(p []byte) (int, error) {
|
||||
// Only copy the data if we have to. Optimistically assume
|
||||
// that p will contain a complete header block.
|
||||
if d.saveBuf.Len() == 0 {
|
||||
d.buf = p
|
||||
} else {
|
||||
d.saveBuf.Write(p)
|
||||
d.buf = d.saveBuf.Bytes()
|
||||
d.saveBuf.Reset()
|
||||
}
|
||||
|
||||
if err := d.decode(); err != nil {
|
||||
if err != errNeedMore {
|
||||
return 0, err
|
||||
}
|
||||
// TODO: limit the size of the buffer
|
||||
d.saveBuf.Write(d.buf)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// DecodeFull decodes an entire block.
|
||||
func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
|
||||
if len(p) == 0 {
|
||||
return []HeaderField{}, nil
|
||||
}
|
||||
|
||||
d.mutex.Lock()
|
||||
defer d.mutex.Unlock()
|
||||
|
||||
saveFunc := d.emitFunc
|
||||
defer func() { d.emitFunc = saveFunc }()
|
||||
|
||||
var hf []HeaderField
|
||||
d.emitFunc = func(f HeaderField) { hf = append(hf, f) }
|
||||
if _, err := d.writeLocked(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := d.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hf, nil
|
||||
}
|
||||
|
||||
// Close declares that the decoding is complete and resets the Decoder
|
||||
// to be reused again for a new header block. If there is any remaining
|
||||
// data in the decoder's buffer, Close returns an error.
|
||||
func (d *Decoder) Close() error {
|
||||
if d.saveBuf.Len() > 0 {
|
||||
d.saveBuf.Reset()
|
||||
return decodingError{errors.New("truncated headers")}
|
||||
}
|
||||
d.readRequiredInsertCount = false
|
||||
d.readDeltaBase = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decode() error {
|
||||
if !d.readRequiredInsertCount {
|
||||
requiredInsertCount, rest, err := readVarInt(8, d.buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.readRequiredInsertCount = true
|
||||
if requiredInsertCount != 0 {
|
||||
return decodingError{errors.New("expected Required Insert Count to be zero")}
|
||||
}
|
||||
d.buf = rest
|
||||
}
|
||||
if !d.readDeltaBase {
|
||||
base, rest, err := readVarInt(7, d.buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.readDeltaBase = true
|
||||
if base != 0 {
|
||||
return decodingError{errors.New("expected Base to be zero")}
|
||||
}
|
||||
d.buf = rest
|
||||
}
|
||||
if len(d.buf) == 0 {
|
||||
return errNeedMore
|
||||
}
|
||||
|
||||
for len(d.buf) > 0 {
|
||||
b := d.buf[0]
|
||||
var err error
|
||||
switch {
|
||||
case b&0x80 > 0: // 1xxxxxxx
|
||||
err = d.parseIndexedHeaderField()
|
||||
case b&0xc0 == 0x40: // 01xxxxxx
|
||||
err = d.parseLiteralHeaderField()
|
||||
case b&0xe0 == 0x20: // 001xxxxx
|
||||
err = d.parseLiteralHeaderFieldWithoutNameReference()
|
||||
default:
|
||||
err = fmt.Errorf("unexpected type byte: %#x", b)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) parseIndexedHeaderField() error {
|
||||
buf := d.buf
|
||||
if buf[0]&0x40 == 0 {
|
||||
return errNoDynamicTable
|
||||
}
|
||||
index, buf, err := readVarInt(6, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hf, ok := d.at(index)
|
||||
if !ok {
|
||||
return decodingError{invalidIndexError(index)}
|
||||
}
|
||||
d.emitFunc(hf)
|
||||
d.buf = buf
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) parseLiteralHeaderField() error {
|
||||
buf := d.buf
|
||||
if buf[0]&0x20 > 0 || buf[0]&0x10 == 0 {
|
||||
return errNoDynamicTable
|
||||
}
|
||||
index, buf, err := readVarInt(4, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hf, ok := d.at(index)
|
||||
if !ok {
|
||||
return decodingError{invalidIndexError(index)}
|
||||
}
|
||||
if len(buf) == 0 {
|
||||
return errNeedMore
|
||||
}
|
||||
usesHuffman := buf[0]&0x80 > 0
|
||||
val, buf, err := d.readString(buf, 7, usesHuffman)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hf.Value = val
|
||||
d.emitFunc(hf)
|
||||
d.buf = buf
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) parseLiteralHeaderFieldWithoutNameReference() error {
|
||||
buf := d.buf
|
||||
usesHuffmanForName := buf[0]&0x8 > 0
|
||||
name, buf, err := d.readString(buf, 3, usesHuffmanForName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(buf) == 0 {
|
||||
return errNeedMore
|
||||
}
|
||||
usesHuffmanForVal := buf[0]&0x80 > 0
|
||||
val, buf, err := d.readString(buf, 7, usesHuffmanForVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.emitFunc(HeaderField{Name: name, Value: val})
|
||||
d.buf = buf
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) readString(buf []byte, n uint8, usesHuffman bool) (string, []byte, error) {
|
||||
l, buf, err := readVarInt(n, buf)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if uint64(len(buf)) < l {
|
||||
return "", nil, errNeedMore
|
||||
}
|
||||
var val string
|
||||
if usesHuffman {
|
||||
var err error
|
||||
val, err = hpack.HuffmanDecodeToString(buf[:l])
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
} else {
|
||||
val = string(buf[:l])
|
||||
}
|
||||
buf = buf[l:]
|
||||
return val, buf, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
|
||||
if i >= uint64(len(staticTableEntries)) {
|
||||
return
|
||||
}
|
||||
return staticTableEntries[i], true
|
||||
}
|
||||
95
vendor/github.com/quic-go/qpack/encoder.go
generated
vendored
Normal file
95
vendor/github.com/quic-go/qpack/encoder.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
package qpack
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
// An Encoder performs QPACK encoding.
|
||||
type Encoder struct {
|
||||
wrotePrefix bool
|
||||
|
||||
w io.Writer
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// NewEncoder returns a new Encoder which performs QPACK encoding. An
|
||||
// encoded data is written to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w}
|
||||
}
|
||||
|
||||
// WriteField encodes f into a single Write to e's underlying Writer.
|
||||
// This function may also produce bytes for the Header Block Prefix
|
||||
// if necessary. If produced, it is done before encoding f.
|
||||
func (e *Encoder) WriteField(f HeaderField) error {
|
||||
// write the Header Block Prefix
|
||||
if !e.wrotePrefix {
|
||||
e.buf = appendVarInt(e.buf, 8, 0)
|
||||
e.buf = appendVarInt(e.buf, 7, 0)
|
||||
e.wrotePrefix = true
|
||||
}
|
||||
|
||||
idxAndVals, nameFound := encoderMap[f.Name]
|
||||
if nameFound {
|
||||
if idxAndVals.values == nil {
|
||||
if len(f.Value) == 0 {
|
||||
e.writeIndexedField(idxAndVals.idx)
|
||||
} else {
|
||||
e.writeLiteralFieldWithNameReference(&f, idxAndVals.idx)
|
||||
}
|
||||
} else {
|
||||
valIdx, valueFound := idxAndVals.values[f.Value]
|
||||
if valueFound {
|
||||
e.writeIndexedField(valIdx)
|
||||
} else {
|
||||
e.writeLiteralFieldWithNameReference(&f, idxAndVals.idx)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
e.writeLiteralFieldWithoutNameReference(f)
|
||||
}
|
||||
|
||||
_, err := e.w.Write(e.buf)
|
||||
e.buf = e.buf[:0]
|
||||
return err
|
||||
}
|
||||
|
||||
// Close declares that the encoding is complete and resets the Encoder
|
||||
// to be reused again for a new header block.
|
||||
func (e *Encoder) Close() error {
|
||||
e.wrotePrefix = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) writeLiteralFieldWithoutNameReference(f HeaderField) {
|
||||
offset := len(e.buf)
|
||||
e.buf = appendVarInt(e.buf, 3, hpack.HuffmanEncodeLength(f.Name))
|
||||
e.buf[offset] ^= 0x20 ^ 0x8
|
||||
e.buf = hpack.AppendHuffmanString(e.buf, f.Name)
|
||||
offset = len(e.buf)
|
||||
e.buf = appendVarInt(e.buf, 7, hpack.HuffmanEncodeLength(f.Value))
|
||||
e.buf[offset] ^= 0x80
|
||||
e.buf = hpack.AppendHuffmanString(e.buf, f.Value)
|
||||
}
|
||||
|
||||
// Encodes a header field whose name is present in one of the tables.
|
||||
func (e *Encoder) writeLiteralFieldWithNameReference(f *HeaderField, id uint8) {
|
||||
offset := len(e.buf)
|
||||
e.buf = appendVarInt(e.buf, 4, uint64(id))
|
||||
// Set the 01NTxxxx pattern, forcing N to 0 and T to 1
|
||||
e.buf[offset] ^= 0x50
|
||||
offset = len(e.buf)
|
||||
e.buf = appendVarInt(e.buf, 7, hpack.HuffmanEncodeLength(f.Value))
|
||||
e.buf[offset] ^= 0x80
|
||||
e.buf = hpack.AppendHuffmanString(e.buf, f.Value)
|
||||
}
|
||||
|
||||
// Encodes an indexed field, meaning it's entirely defined in one of the tables.
|
||||
func (e *Encoder) writeIndexedField(id uint8) {
|
||||
offset := len(e.buf)
|
||||
e.buf = appendVarInt(e.buf, 6, uint64(id))
|
||||
// Set the 1Txxxxxx pattern, forcing T to 1
|
||||
e.buf[offset] ^= 0xc0
|
||||
}
|
||||
16
vendor/github.com/quic-go/qpack/header_field.go
generated
vendored
Normal file
16
vendor/github.com/quic-go/qpack/header_field.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package qpack
|
||||
|
||||
// A HeaderField is a name-value pair. Both the name and value are
|
||||
// treated as opaque sequences of octets.
|
||||
type HeaderField struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
// IsPseudo reports whether the header field is an HTTP3 pseudo header.
|
||||
// That is, it reports whether it starts with a colon.
|
||||
// It is not otherwise guaranteed to be a valid pseudo header field,
|
||||
// though.
|
||||
func (hf HeaderField) IsPseudo() bool {
|
||||
return len(hf.Name) != 0 && hf.Name[0] == ':'
|
||||
}
|
||||
255
vendor/github.com/quic-go/qpack/static_table.go
generated
vendored
Normal file
255
vendor/github.com/quic-go/qpack/static_table.go
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
package qpack
|
||||
|
||||
var staticTableEntries = [...]HeaderField{
|
||||
{Name: ":authority"},
|
||||
{Name: ":path", Value: "/"},
|
||||
{Name: "age", Value: "0"},
|
||||
{Name: "content-disposition"},
|
||||
{Name: "content-length", Value: "0"},
|
||||
{Name: "cookie"},
|
||||
{Name: "date"},
|
||||
{Name: "etag"},
|
||||
{Name: "if-modified-since"},
|
||||
{Name: "if-none-match"},
|
||||
{Name: "last-modified"},
|
||||
{Name: "link"},
|
||||
{Name: "location"},
|
||||
{Name: "referer"},
|
||||
{Name: "set-cookie"},
|
||||
{Name: ":method", Value: "CONNECT"},
|
||||
{Name: ":method", Value: "DELETE"},
|
||||
{Name: ":method", Value: "GET"},
|
||||
{Name: ":method", Value: "HEAD"},
|
||||
{Name: ":method", Value: "OPTIONS"},
|
||||
{Name: ":method", Value: "POST"},
|
||||
{Name: ":method", Value: "PUT"},
|
||||
{Name: ":scheme", Value: "http"},
|
||||
{Name: ":scheme", Value: "https"},
|
||||
{Name: ":status", Value: "103"},
|
||||
{Name: ":status", Value: "200"},
|
||||
{Name: ":status", Value: "304"},
|
||||
{Name: ":status", Value: "404"},
|
||||
{Name: ":status", Value: "503"},
|
||||
{Name: "accept", Value: "*/*"},
|
||||
{Name: "accept", Value: "application/dns-message"},
|
||||
{Name: "accept-encoding", Value: "gzip, deflate, br"},
|
||||
{Name: "accept-ranges", Value: "bytes"},
|
||||
{Name: "access-control-allow-headers", Value: "cache-control"},
|
||||
{Name: "access-control-allow-headers", Value: "content-type"},
|
||||
{Name: "access-control-allow-origin", Value: "*"},
|
||||
{Name: "cache-control", Value: "max-age=0"},
|
||||
{Name: "cache-control", Value: "max-age=2592000"},
|
||||
{Name: "cache-control", Value: "max-age=604800"},
|
||||
{Name: "cache-control", Value: "no-cache"},
|
||||
{Name: "cache-control", Value: "no-store"},
|
||||
{Name: "cache-control", Value: "public, max-age=31536000"},
|
||||
{Name: "content-encoding", Value: "br"},
|
||||
{Name: "content-encoding", Value: "gzip"},
|
||||
{Name: "content-type", Value: "application/dns-message"},
|
||||
{Name: "content-type", Value: "application/javascript"},
|
||||
{Name: "content-type", Value: "application/json"},
|
||||
{Name: "content-type", Value: "application/x-www-form-urlencoded"},
|
||||
{Name: "content-type", Value: "image/gif"},
|
||||
{Name: "content-type", Value: "image/jpeg"},
|
||||
{Name: "content-type", Value: "image/png"},
|
||||
{Name: "content-type", Value: "text/css"},
|
||||
{Name: "content-type", Value: "text/html; charset=utf-8"},
|
||||
{Name: "content-type", Value: "text/plain"},
|
||||
{Name: "content-type", Value: "text/plain;charset=utf-8"},
|
||||
{Name: "range", Value: "bytes=0-"},
|
||||
{Name: "strict-transport-security", Value: "max-age=31536000"},
|
||||
{Name: "strict-transport-security", Value: "max-age=31536000; includesubdomains"},
|
||||
{Name: "strict-transport-security", Value: "max-age=31536000; includesubdomains; preload"},
|
||||
{Name: "vary", Value: "accept-encoding"},
|
||||
{Name: "vary", Value: "origin"},
|
||||
{Name: "x-content-type-options", Value: "nosniff"},
|
||||
{Name: "x-xss-protection", Value: "1; mode=block"},
|
||||
{Name: ":status", Value: "100"},
|
||||
{Name: ":status", Value: "204"},
|
||||
{Name: ":status", Value: "206"},
|
||||
{Name: ":status", Value: "302"},
|
||||
{Name: ":status", Value: "400"},
|
||||
{Name: ":status", Value: "403"},
|
||||
{Name: ":status", Value: "421"},
|
||||
{Name: ":status", Value: "425"},
|
||||
{Name: ":status", Value: "500"},
|
||||
{Name: "accept-language"},
|
||||
{Name: "access-control-allow-credentials", Value: "FALSE"},
|
||||
{Name: "access-control-allow-credentials", Value: "TRUE"},
|
||||
{Name: "access-control-allow-headers", Value: "*"},
|
||||
{Name: "access-control-allow-methods", Value: "get"},
|
||||
{Name: "access-control-allow-methods", Value: "get, post, options"},
|
||||
{Name: "access-control-allow-methods", Value: "options"},
|
||||
{Name: "access-control-expose-headers", Value: "content-length"},
|
||||
{Name: "access-control-request-headers", Value: "content-type"},
|
||||
{Name: "access-control-request-method", Value: "get"},
|
||||
{Name: "access-control-request-method", Value: "post"},
|
||||
{Name: "alt-svc", Value: "clear"},
|
||||
{Name: "authorization"},
|
||||
{Name: "content-security-policy", Value: "script-src 'none'; object-src 'none'; base-uri 'none'"},
|
||||
{Name: "early-data", Value: "1"},
|
||||
{Name: "expect-ct"},
|
||||
{Name: "forwarded"},
|
||||
{Name: "if-range"},
|
||||
{Name: "origin"},
|
||||
{Name: "purpose", Value: "prefetch"},
|
||||
{Name: "server"},
|
||||
{Name: "timing-allow-origin", Value: "*"},
|
||||
{Name: "upgrade-insecure-requests", Value: "1"},
|
||||
{Name: "user-agent"},
|
||||
{Name: "x-forwarded-for"},
|
||||
{Name: "x-frame-options", Value: "deny"},
|
||||
{Name: "x-frame-options", Value: "sameorigin"},
|
||||
}
|
||||
|
||||
// Only needed for tests.
|
||||
// use go:linkname to retrieve the static table.
|
||||
//
|
||||
//nolint:deadcode,unused
|
||||
func getStaticTable() []HeaderField {
|
||||
return staticTableEntries[:]
|
||||
}
|
||||
|
||||
type indexAndValues struct {
|
||||
idx uint8
|
||||
values map[string]uint8
|
||||
}
|
||||
|
||||
// A map of the header names from the static table to their index in the table.
|
||||
// This is used by the encoder to quickly find if a header is in the static table
|
||||
// and what value should be used to encode it.
|
||||
// There's a second level of mapping for the headers that have some predefined
|
||||
// values in the static table.
|
||||
var encoderMap = map[string]indexAndValues{
|
||||
":authority": {0, nil},
|
||||
":path": {1, map[string]uint8{"/": 1}},
|
||||
"age": {2, map[string]uint8{"0": 2}},
|
||||
"content-disposition": {3, nil},
|
||||
"content-length": {4, map[string]uint8{"0": 4}},
|
||||
"cookie": {5, nil},
|
||||
"date": {6, nil},
|
||||
"etag": {7, nil},
|
||||
"if-modified-since": {8, nil},
|
||||
"if-none-match": {9, nil},
|
||||
"last-modified": {10, nil},
|
||||
"link": {11, nil},
|
||||
"location": {12, nil},
|
||||
"referer": {13, nil},
|
||||
"set-cookie": {14, nil},
|
||||
":method": {15, map[string]uint8{
|
||||
"CONNECT": 15,
|
||||
"DELETE": 16,
|
||||
"GET": 17,
|
||||
"HEAD": 18,
|
||||
"OPTIONS": 19,
|
||||
"POST": 20,
|
||||
"PUT": 21,
|
||||
}},
|
||||
":scheme": {22, map[string]uint8{
|
||||
"http": 22,
|
||||
"https": 23,
|
||||
}},
|
||||
":status": {24, map[string]uint8{
|
||||
"103": 24,
|
||||
"200": 25,
|
||||
"304": 26,
|
||||
"404": 27,
|
||||
"503": 28,
|
||||
"100": 63,
|
||||
"204": 64,
|
||||
"206": 65,
|
||||
"302": 66,
|
||||
"400": 67,
|
||||
"403": 68,
|
||||
"421": 69,
|
||||
"425": 70,
|
||||
"500": 71,
|
||||
}},
|
||||
"accept": {29, map[string]uint8{
|
||||
"*/*": 29,
|
||||
"application/dns-message": 30,
|
||||
}},
|
||||
"accept-encoding": {31, map[string]uint8{"gzip, deflate, br": 31}},
|
||||
"accept-ranges": {32, map[string]uint8{"bytes": 32}},
|
||||
"access-control-allow-headers": {33, map[string]uint8{
|
||||
"cache-control": 33,
|
||||
"content-type": 34,
|
||||
"*": 75,
|
||||
}},
|
||||
"access-control-allow-origin": {35, map[string]uint8{"*": 35}},
|
||||
"cache-control": {36, map[string]uint8{
|
||||
"max-age=0": 36,
|
||||
"max-age=2592000": 37,
|
||||
"max-age=604800": 38,
|
||||
"no-cache": 39,
|
||||
"no-store": 40,
|
||||
"public, max-age=31536000": 41,
|
||||
}},
|
||||
"content-encoding": {42, map[string]uint8{
|
||||
"br": 42,
|
||||
"gzip": 43,
|
||||
}},
|
||||
"content-type": {44, map[string]uint8{
|
||||
"application/dns-message": 44,
|
||||
"application/javascript": 45,
|
||||
"application/json": 46,
|
||||
"application/x-www-form-urlencoded": 47,
|
||||
"image/gif": 48,
|
||||
"image/jpeg": 49,
|
||||
"image/png": 50,
|
||||
"text/css": 51,
|
||||
"text/html; charset=utf-8": 52,
|
||||
"text/plain": 53,
|
||||
"text/plain;charset=utf-8": 54,
|
||||
}},
|
||||
"range": {55, map[string]uint8{"bytes=0-": 55}},
|
||||
"strict-transport-security": {56, map[string]uint8{
|
||||
"max-age=31536000": 56,
|
||||
"max-age=31536000; includesubdomains": 57,
|
||||
"max-age=31536000; includesubdomains; preload": 58,
|
||||
}},
|
||||
"vary": {59, map[string]uint8{
|
||||
"accept-encoding": 59,
|
||||
"origin": 60,
|
||||
}},
|
||||
"x-content-type-options": {61, map[string]uint8{"nosniff": 61}},
|
||||
"x-xss-protection": {62, map[string]uint8{"1; mode=block": 62}},
|
||||
// ":status" is duplicated and takes index 63 to 71
|
||||
"accept-language": {72, nil},
|
||||
"access-control-allow-credentials": {73, map[string]uint8{
|
||||
"FALSE": 73,
|
||||
"TRUE": 74,
|
||||
}},
|
||||
// "access-control-allow-headers" is duplicated and takes index 75
|
||||
"access-control-allow-methods": {76, map[string]uint8{
|
||||
"get": 76,
|
||||
"get, post, options": 77,
|
||||
"options": 78,
|
||||
}},
|
||||
"access-control-expose-headers": {79, map[string]uint8{"content-length": 79}},
|
||||
"access-control-request-headers": {80, map[string]uint8{"content-type": 80}},
|
||||
"access-control-request-method": {81, map[string]uint8{
|
||||
"get": 81,
|
||||
"post": 82,
|
||||
}},
|
||||
"alt-svc": {83, map[string]uint8{"clear": 83}},
|
||||
"authorization": {84, nil},
|
||||
"content-security-policy": {85, map[string]uint8{
|
||||
"script-src 'none'; object-src 'none'; base-uri 'none'": 85,
|
||||
}},
|
||||
"early-data": {86, map[string]uint8{"1": 86}},
|
||||
"expect-ct": {87, nil},
|
||||
"forwarded": {88, nil},
|
||||
"if-range": {89, nil},
|
||||
"origin": {90, nil},
|
||||
"purpose": {91, map[string]uint8{"prefetch": 91}},
|
||||
"server": {92, nil},
|
||||
"timing-allow-origin": {93, map[string]uint8{"*": 93}},
|
||||
"upgrade-insecure-requests": {94, map[string]uint8{"1": 94}},
|
||||
"user-agent": {95, nil},
|
||||
"x-forwarded-for": {96, nil},
|
||||
"x-frame-options": {97, map[string]uint8{
|
||||
"deny": 97,
|
||||
"sameorigin": 98,
|
||||
}},
|
||||
}
|
||||
5
vendor/github.com/quic-go/qpack/tools.go
generated
vendored
Normal file
5
vendor/github.com/quic-go/qpack/tools.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
//go:build tools
|
||||
|
||||
package qpack
|
||||
|
||||
import _ "github.com/onsi/ginkgo/v2/ginkgo"
|
||||
66
vendor/github.com/quic-go/qpack/varint.go
generated
vendored
Normal file
66
vendor/github.com/quic-go/qpack/varint.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package qpack
|
||||
|
||||
// copied from the Go standard library HPACK implementation
|
||||
|
||||
import "errors"
|
||||
|
||||
var errVarintOverflow = errors.New("varint integer overflow")
|
||||
|
||||
// appendVarInt appends i, as encoded in variable integer form using n
|
||||
// bit prefix, to dst and returns the extended buffer.
|
||||
//
|
||||
// See
|
||||
// http://http2.github.io/http2-spec/compression.html#integer.representation
|
||||
func appendVarInt(dst []byte, n byte, i uint64) []byte {
|
||||
k := uint64((1 << n) - 1)
|
||||
if i < k {
|
||||
return append(dst, byte(i))
|
||||
}
|
||||
dst = append(dst, byte(k))
|
||||
i -= k
|
||||
for ; i >= 128; i >>= 7 {
|
||||
dst = append(dst, byte(0x80|(i&0x7f)))
|
||||
}
|
||||
return append(dst, byte(i))
|
||||
}
|
||||
|
||||
// readVarInt reads an unsigned variable length integer off the
|
||||
// beginning of p. n is the parameter as described in
|
||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
|
||||
//
|
||||
// n must always be between 1 and 8.
|
||||
//
|
||||
// The returned remain buffer is either a smaller suffix of p, or err != nil.
|
||||
// The error is errNeedMore if p doesn't contain a complete integer.
|
||||
func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
|
||||
if n < 1 || n > 8 {
|
||||
panic("bad n")
|
||||
}
|
||||
if len(p) == 0 {
|
||||
return 0, p, errNeedMore
|
||||
}
|
||||
i = uint64(p[0])
|
||||
if n < 8 {
|
||||
i &= (1 << uint64(n)) - 1
|
||||
}
|
||||
if i < (1<<uint64(n))-1 {
|
||||
return i, p[1:], nil
|
||||
}
|
||||
|
||||
origP := p
|
||||
p = p[1:]
|
||||
var m uint64
|
||||
for len(p) > 0 {
|
||||
b := p[0]
|
||||
p = p[1:]
|
||||
i += uint64(b&127) << m
|
||||
if b&128 == 0 {
|
||||
return i, p, nil
|
||||
}
|
||||
m += 7
|
||||
if m >= 63 { // TODO: proper overflow check. making this up.
|
||||
return 0, origP, errVarintOverflow
|
||||
}
|
||||
}
|
||||
return 0, origP, errNeedMore
|
||||
}
|
||||
Reference in New Issue
Block a user