github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/transports/header.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package transports 19 20 import ( 21 "bytes" 22 "github.com/aacfactory/fns/commons/bytex" 23 "net/textproto" 24 "sort" 25 "strconv" 26 "sync" 27 ) 28 29 var ( 30 ContentTypeHeaderName = []byte("Content-Type") 31 ContentTypeJsonHeaderValue = []byte("application/json") 32 ContentTypeTextHeaderValue = []byte("text/plain") 33 ContentTypeAvroHeaderValue = []byte("application/avro") 34 ContentLengthHeaderName = []byte("Content-Length") 35 AuthorizationHeaderName = []byte("Authorization") 36 CookieHeaderName = []byte("Cookie") 37 ConnectionHeaderName = []byte("Connection") 38 UpgradeHeaderName = []byte("Upgrade") 39 CloseHeaderValue = []byte("close") 40 AcceptEncodingHeaderName = []byte("Accept-Encoding") 41 ContentEncodingHeaderName = []byte("Content-Encoding") 42 ClearSiteDataHeaderName = []byte("Clear-Site-Data") 43 CacheControlHeaderName = []byte("Cache-Control") 44 AgeHeaderName = []byte("Age") 45 CacheControlHeaderNoStore = []byte("no-store") 46 CacheControlHeaderNoCache = []byte("no-cache") 47 ETagHeaderName = []byte("ETag") 48 CacheControlHeaderIfNonMatch = []byte("If-None-Match") 49 VaryHeaderName = []byte("Vary") 50 OriginHeaderName = []byte("Origin") 51 AcceptHeaderName = []byte("Accept") 52 AccessControlRequestMethodHeaderName = []byte("Access-Control-Request-Method") 53 AccessControlRequestHeadersHeaderName = []byte("Access-Control-Request-Headers") 54 AccessControlRequestPrivateNetworkHeaderName = []byte("Access-Control-Request-Private-Network") 55 AccessControlAllowOriginHeaderName = []byte("Access-Control-Allow-Origin") 56 AccessControlAllowMethodsHeaderName = []byte("Access-Control-Allow-Methods") 57 AccessControlAllowHeadersHeaderName = []byte("Access-Control-Allow-Headers") 58 AccessControlAllowCredentialsHeaderName = []byte("Access-Control-Allow-Credentials") 59 AccessControlAllowPrivateNetworkHeaderName = []byte("Access-Control-Allow-Private-Network") 60 AccessControlMaxAgeHeaderName = []byte("Access-Control-Max-Age") 61 AccessControlExposeHeadersHeaderName = []byte("Access-Control-Expose-Headers") 62 XRequestedWithHeaderName = []byte("X-Requested-With") 63 TrueClientIpHeaderName = []byte("True-Client-Ip") 64 XRealIpHeaderName = []byte("X-Real-IP") 65 XForwardedForHeaderName = []byte("X-Forwarded-For") 66 RequestIdHeaderName = []byte("X-Fns-Request-Id") 67 SignatureHeaderName = []byte("X-Fns-Signature") 68 EndpointIdHeaderName = []byte("X-Fns-Endpoint-Id") 69 EndpointVersionHeaderName = []byte("X-Fns-Endpoint-Version") 70 RequestTimeoutHeaderName = []byte("X-Fns-Request-Timeout") 71 RequestVersionsHeaderName = []byte("X-Fns-Request-Version") 72 HandleLatencyHeaderName = []byte("X-Fns-Handle-Latency") 73 DeviceIdHeaderName = []byte("X-Fns-Device-Id") 74 DeviceIpHeaderName = []byte("X-Fns-Device-Ip") 75 DeprecatedHeaderName = []byte("X-Fns-Deprecated") 76 ResponseRetryAfterHeaderName = []byte("Retry-After") 77 UserHeaderNamePrefix = []byte("XU-") 78 ) 79 80 type Header interface { 81 Add(key []byte, value []byte) 82 Set(key []byte, value []byte) 83 Get(key []byte) []byte 84 Del(key []byte) 85 Values(key []byte) [][]byte 86 Foreach(fn func(key []byte, values [][]byte)) 87 Len() int 88 Reset() 89 } 90 91 var ( 92 headerPool = sync.Pool{} 93 ) 94 95 func AcquireHeader() Header { 96 cached := headerPool.Get() 97 if cached == nil { 98 return NewHeader() 99 } 100 return cached.(Header) 101 } 102 103 func ReleaseHeader(h Header) { 104 h.Reset() 105 headerPool.Put(h) 106 } 107 108 func NewHeader() Header { 109 hh := make(defaultHeader, 0, 1) 110 return &hh 111 } 112 113 type headerEntry struct { 114 name []byte 115 value [][]byte 116 } 117 118 type defaultHeader []headerEntry 119 120 func (h *defaultHeader) Add(key []byte, value []byte) { 121 hh := *h 122 key = bytex.FromString(textproto.CanonicalMIMEHeaderKey(bytex.ToString(key))) 123 for _, entry := range hh { 124 if bytes.Equal(entry.name, key) { 125 entry.value = append(entry.value, value) 126 return 127 } 128 } 129 hh = append(hh, headerEntry{ 130 name: key, 131 value: [][]byte{value}, 132 }) 133 *h = hh 134 } 135 136 func (h *defaultHeader) Set(key []byte, value []byte) { 137 hh := *h 138 key = bytex.FromString(textproto.CanonicalMIMEHeaderKey(bytex.ToString(key))) 139 for _, entry := range hh { 140 if bytes.Equal(entry.name, key) { 141 entry.value = [][]byte{value} 142 return 143 } 144 } 145 hh = append(hh, headerEntry{ 146 name: key, 147 value: [][]byte{value}, 148 }) 149 *h = hh 150 } 151 152 func (h *defaultHeader) Get(key []byte) []byte { 153 hh := *h 154 key = bytex.FromString(textproto.CanonicalMIMEHeaderKey(bytex.ToString(key))) 155 for _, entry := range hh { 156 if bytes.Equal(entry.name, key) { 157 return entry.value[0] 158 } 159 } 160 return nil 161 } 162 163 func (h *defaultHeader) Del(key []byte) { 164 hh := *h 165 key = bytex.FromString(textproto.CanonicalMIMEHeaderKey(bytex.ToString(key))) 166 n := -1 167 for i, entry := range hh { 168 if bytes.Equal(entry.name, key) { 169 n = i 170 break 171 } 172 } 173 if n == -1 { 174 return 175 } 176 hh = append(hh[:n], hh[n+1:]...) 177 *h = hh 178 } 179 180 func (h *defaultHeader) Values(key []byte) [][]byte { 181 hh := *h 182 key = bytex.FromString(textproto.CanonicalMIMEHeaderKey(bytex.ToString(key))) 183 for _, entry := range hh { 184 if bytes.Equal(entry.name, key) { 185 return entry.value 186 } 187 } 188 return nil 189 } 190 191 func (h *defaultHeader) Len() int { 192 return len(*h) 193 } 194 195 func (h *defaultHeader) Foreach(fn func(key []byte, values [][]byte)) { 196 hh := *h 197 for _, entry := range hh { 198 fn(entry.name, entry.value) 199 } 200 } 201 202 func (h *defaultHeader) Reset() { 203 hh := *h 204 hh = hh[:0] 205 *h = hh 206 } 207 208 type AcceptEncoding struct { 209 Name []byte 210 Quality float64 211 } 212 213 type AcceptEncodings []AcceptEncoding 214 215 func (encodings AcceptEncodings) Len() int { 216 return len(encodings) 217 } 218 219 func (encodings AcceptEncodings) Less(i, j int) bool { 220 return encodings[i].Quality < encodings[j].Quality 221 } 222 223 func (encodings AcceptEncodings) Swap(i, j int) { 224 encodings[i], encodings[j] = encodings[j], encodings[i] 225 } 226 227 func (encodings AcceptEncodings) Get(name []byte) (quality float64, has bool) { 228 for _, enc := range encodings { 229 if bytes.Equal(enc.Name, name) { 230 quality = enc.Quality 231 has = true 232 return 233 } 234 } 235 return 236 } 237 238 func (encodings AcceptEncodings) Add(name []byte, quality float64) AcceptEncodings { 239 return append(encodings, AcceptEncoding{ 240 Name: name, 241 Quality: quality, 242 }) 243 } 244 245 func (encodings AcceptEncodings) WriteTo(header Header) { 246 p := make([]byte, 0, 1) 247 for i, encoding := range encodings { 248 if i > 0 { 249 p = append(p, ',', ' ') 250 } 251 p = append(encoding.Name) 252 if encoding.Quality > 0 { 253 p = append(p, ';') 254 } 255 p = append(p, bytex.FromString(strconv.FormatFloat(encoding.Quality, 'f', 1, 64))...) 256 } 257 header.Set(AcceptEncodingHeaderName, p) 258 } 259 260 var ( 261 comma = []byte{','} 262 semicolon = []byte{';'} 263 ) 264 265 func GetAcceptEncodings(header Header) (encodings AcceptEncodings) { 266 p := header.Get(AcceptEncodingHeaderName) 267 if len(p) == 0 { 268 return 269 } 270 items := bytes.Split(p, comma) 271 encodings = make(AcceptEncodings, 0, len(items)) 272 for _, item := range items { 273 idx := bytes.Index(item, semicolon) 274 if idx < 0 { 275 item = bytes.TrimSpace(item) 276 if len(item) == 0 { 277 continue 278 } 279 encodings = append(encodings, AcceptEncoding{ 280 Name: item, 281 Quality: 0, 282 }) 283 continue 284 } 285 if idx == len(item) { 286 item = bytes.TrimSpace(item[0 : idx-1]) 287 if len(item) == 0 { 288 continue 289 } 290 encodings = append(encodings, AcceptEncoding{ 291 Name: item, 292 Quality: 0, 293 }) 294 continue 295 } 296 name := bytes.TrimSpace(item[0:idx]) 297 if len(name) == 0 { 298 continue 299 } 300 qp := bytes.TrimSpace(bytes.TrimSpace(item[idx+1:])) 301 quality, qualityErr := strconv.ParseFloat(bytex.ToString(qp), 64) 302 if qualityErr != nil { 303 continue 304 } 305 encodings = append(encodings, AcceptEncoding{ 306 Name: name, 307 Quality: quality, 308 }) 309 } 310 if len(encodings) == 0 { 311 return 312 } 313 sort.Sort(encodings) 314 return 315 } 316 317 func AddXU(header Header, name []byte, value []byte) { 318 if idx := bytes.Index(name, UserHeaderNamePrefix); idx < 0 { 319 name = append(UserHeaderNamePrefix, name...) 320 } 321 header.Add(name, value) 322 } 323 324 func SetXU(header Header, name []byte, value []byte) { 325 if idx := bytes.Index(name, UserHeaderNamePrefix); idx < 0 { 326 name = append(UserHeaderNamePrefix, name...) 327 } 328 header.Set(name, value) 329 } 330 331 func GetXU(header Header, name []byte) (value []byte) { 332 if idx := bytes.Index(name, UserHeaderNamePrefix); idx < 0 { 333 name = append(UserHeaderNamePrefix, name...) 334 } 335 value = header.Get(name) 336 return 337 } 338 339 func ValuesXU(header Header, name []byte) (value [][]byte) { 340 if idx := bytes.Index(name, UserHeaderNamePrefix); idx < 0 { 341 name = append(UserHeaderNamePrefix, name...) 342 } 343 value = header.Values(name) 344 return 345 }