Help us shape the future of Go! Take the 2026 Go Developer Survey

headerlist

package
v3.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package headerlist walks the comma-separated list values that RFC 9110 Section 5.6.1 defines, and joins the field lines that Section 5.3 says are equivalent to one.

Seven scanners used to spell this out separately: three in the core (helpers.go, ctx.go, res.go) and four in middleware (adaptor, proxy, compress, cache). They agreed on splitting at commas and trimming OWS, and disagreed on everything after that, so the divergences are named here rather than left to be rediscovered per call site:

  • Case. Contains compares exactly, ContainsFold under ASCII case folding. AppendUnique and AppendUniqueFold follow the same split. Append echoes list members as written. Vary members are HTTP field names and must match however they arrive (RFC 9110 Section 5.1).
  • Quoting. All treats every comma as a separator, which is what a list of bare tokens wants. AllQuoted keeps commas that sit inside a quoted string, which is what a list of entity tags or media-type parameters needs, since those may contain one.
  • Whitespace. All and its siblings trim with utils.TrimSpace, which also takes CR, LF, VT and FF. TrimOWS takes only SP and HTAB, the OWS of RFC 9110 Section 5.6.3, for a caller that validates what is left.

Empty elements are skipped throughout: "a,,b" yields "a" and "b". A list is permitted to carry them (RFC 9110 Section 5.6.1 allows the empty element for legacy reasons) and no caller here has ever wanted one.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All(list string) iter.Seq[string]

All yields each non-empty element of a comma-separated list value, with leading and trailing whitespace removed.

Every comma separates. Use AllQuoted for a list whose elements may contain a quoted comma.

func AllLines

func AllLines(lines [][]byte) iter.Seq[string]

AllLines yields the elements of every field line in order, so that a header sent as one line and the same header sent as several read alike (RFC 9110 Section 5.3).

The lines are read as-is; the caller keeps whatever storage they alias.

func AllQuoted

func AllQuoted(list string) iter.Seq[string]

AllQuoted is All for lists whose elements may contain a comma inside a quoted string, such as If-None-Match, where the opaque-tag `"v1,v2"` is one entity tag and not two elements (RFC 9110 Section 8.8.3).

Only '"' and ',' can affect where an element ends, so the walk jumps between them instead of visiting every byte. A quoted string left open by a malformed value swallows the rest of the list, which keeps a truncated field from splitting into elements the sender did not write.

func AllQuotedPairs

func AllQuotedPairs(list string) iter.Seq[string]

AllQuotedPairs is AllQuoted for quoted strings that may carry a quoted-pair (RFC 9110 Section 5.6.4), such as Cache-Control directive arguments: inside quotes a backslash escapes the next byte, so `ext="a\"", no-transform` has two elements. Entity tags have no quoted-pair and keep using AllQuoted.

func Append

func Append(dst []string, list string) []string

Append appends the elements of list to dst and returns it, reusing dst's storage. It returns nil for an empty list, leaving dst untouched.

This is the allocation-free counterpart to All, for the callers that need the elements to outlive the walk. It is written as a loop rather than over All because it sits on the per-request Accept-Encoding path.

func AppendUnique

func AppendUnique(list string, values []string) string

AppendUnique adds each value that list does not already carry, separated by ", ", and returns the result. It returns "" when nothing was added, so a caller can tell "unchanged" from "changed" without comparing the strings.

Presence is decided by Contains, byte for byte: a value already listed in another case is added again rather than silently dropped, since the field this serves is echoed to the client as written.

Use AppendUniqueFold when the members are HTTP field names.

func AppendUniqueFold

func AppendUniqueFold(list string, values []string) string

AppendUniqueFold is AppendUnique with presence decided by ContainsFold. Use it when the list members are HTTP field names, which RFC 9110 Section 5.1 treats as case-insensitive. The first spelling is kept.

func Contains

func Contains(list, value string) bool

Contains reports whether list has an element equal to value, compared byte for byte. An empty value is never present.

value is matched against the elements All yields, so it is expected to be one element and to carry no OWS of its own: " gzip " is not an element of " gzip ", though "gzip" is.

Use ContainsFold to match a token whose case the sender chose.

func ContainsFold

func ContainsFold(list, value string) bool

ContainsFold reports whether list has an element equal to value under ASCII case folding. An empty value is never present.

func Join

func Join(lines [][]byte) []byte

Join renders the field lines of one header as the single combined value that RFC 9110 Section 5.3 says they are equivalent to, separated by a bare comma.

A lone line is returned as it stands, so the result aliases the caller's storage and must not be retained past it. Only the multi-line case allocates, and that case is rare.

func JoinNext

func JoinNext(combined, line []byte, multiple bool) ([]byte, bool)

JoinNext adds a field line to a value built during a streaming header walk. The first line aliases the caller's storage. On the second line the result takes ownership of a new buffer; later lines reuse it when capacity permits. Use Join when all lines are already available so it can size that buffer once. The bool reports whether at least two lines have been joined.

func TrimOWS

func TrimOWS[S ~string | ~[]byte](s S) S

TrimOWS removes the optional whitespace around a list element or a field value: SP and HTAB, which is all RFC 9110 Section 5.6.3 allows. CR, LF, VT and FF are not OWS, so they stay for a validating caller to reject, as does a tab inside the value.

The result aliases s.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL