headermap.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
  5package httpcommon
  6
  7import (
  8	"net/textproto"
  9	"sync"
 10)
 11
 12var (
 13	commonBuildOnce   sync.Once
 14	commonLowerHeader map[string]string // Go-Canonical-Case -> lower-case
 15	commonCanonHeader map[string]string // lower-case -> Go-Canonical-Case
 16)
 17
 18func buildCommonHeaderMapsOnce() {
 19	commonBuildOnce.Do(buildCommonHeaderMaps)
 20}
 21
 22func buildCommonHeaderMaps() {
 23	common := []string{
 24		"accept",
 25		"accept-charset",
 26		"accept-encoding",
 27		"accept-language",
 28		"accept-ranges",
 29		"age",
 30		"access-control-allow-credentials",
 31		"access-control-allow-headers",
 32		"access-control-allow-methods",
 33		"access-control-allow-origin",
 34		"access-control-expose-headers",
 35		"access-control-max-age",
 36		"access-control-request-headers",
 37		"access-control-request-method",
 38		"allow",
 39		"authorization",
 40		"cache-control",
 41		"content-disposition",
 42		"content-encoding",
 43		"content-language",
 44		"content-length",
 45		"content-location",
 46		"content-range",
 47		"content-type",
 48		"cookie",
 49		"date",
 50		"etag",
 51		"expect",
 52		"expires",
 53		"from",
 54		"host",
 55		"if-match",
 56		"if-modified-since",
 57		"if-none-match",
 58		"if-unmodified-since",
 59		"last-modified",
 60		"link",
 61		"location",
 62		"max-forwards",
 63		"origin",
 64		"proxy-authenticate",
 65		"proxy-authorization",
 66		"range",
 67		"referer",
 68		"refresh",
 69		"retry-after",
 70		"server",
 71		"set-cookie",
 72		"strict-transport-security",
 73		"trailer",
 74		"transfer-encoding",
 75		"user-agent",
 76		"vary",
 77		"via",
 78		"www-authenticate",
 79		"x-forwarded-for",
 80		"x-forwarded-proto",
 81	}
 82	commonLowerHeader = make(map[string]string, len(common))
 83	commonCanonHeader = make(map[string]string, len(common))
 84	for _, v := range common {
 85		chk := textproto.CanonicalMIMEHeaderKey(v)
 86		commonLowerHeader[chk] = v
 87		commonCanonHeader[v] = chk
 88	}
 89}
 90
 91// LowerHeader returns the lowercase form of a header name,
 92// used on the wire for HTTP/2 and HTTP/3 requests.
 93func LowerHeader(v string) (lower string, ascii bool) {
 94	buildCommonHeaderMapsOnce()
 95	if s, ok := commonLowerHeader[v]; ok {
 96		return s, true
 97	}
 98	return asciiToLower(v)
 99}
100
101// CanonicalHeader canonicalizes a header name. (For example, "host" becomes "Host".)
102func CanonicalHeader(v string) string {
103	buildCommonHeaderMapsOnce()
104	if s, ok := commonCanonHeader[v]; ok {
105		return s
106	}
107	return textproto.CanonicalMIMEHeaderKey(v)
108}
109
110// CachedCanonicalHeader returns the canonical form of a well-known header name.
111func CachedCanonicalHeader(v string) (string, bool) {
112	buildCommonHeaderMapsOnce()
113	s, ok := commonCanonHeader[v]
114	return s, ok
115}