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}