golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/http2/http2.go (about) 1 // Copyright 2014 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 5 // Package http2 implements the HTTP/2 protocol. 6 // 7 // This package is low-level and intended to be used directly by very 8 // few people. Most users will use it indirectly through the automatic 9 // use by the net/http package (from Go 1.6 and later). 10 // For use in earlier Go versions see ConfigureServer. (Transport support 11 // requires Go 1.6 or later) 12 // 13 // See https://http2.github.io/ for more information on HTTP/2. 14 // 15 // See https://http2.golang.org/ for a test server running this code. 16 package http2 // import "golang.org/x/net/http2" 17 18 import ( 19 "bufio" 20 "crypto/tls" 21 "fmt" 22 "io" 23 "net/http" 24 "os" 25 "sort" 26 "strconv" 27 "strings" 28 "sync" 29 30 "golang.org/x/net/http/httpguts" 31 ) 32 33 var ( 34 VerboseLogs bool 35 logFrameWrites bool 36 logFrameReads bool 37 inTests bool 38 ) 39 40 func init() { 41 e := os.Getenv("GODEBUG") 42 if strings.Contains(e, "http2debug=1") { 43 VerboseLogs = true 44 } 45 if strings.Contains(e, "http2debug=2") { 46 VerboseLogs = true 47 logFrameWrites = true 48 logFrameReads = true 49 } 50 } 51 52 const ( 53 // ClientPreface is the string that must be sent by new 54 // connections from clients. 55 ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" 56 57 // SETTINGS_MAX_FRAME_SIZE default 58 // https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2 59 initialMaxFrameSize = 16384 60 61 // NextProtoTLS is the NPN/ALPN protocol negotiated during 62 // HTTP/2's TLS setup. 63 NextProtoTLS = "h2" 64 65 // https://httpwg.org/specs/rfc7540.html#SettingValues 66 initialHeaderTableSize = 4096 67 68 initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size 69 70 defaultMaxReadFrameSize = 1 << 20 71 ) 72 73 var ( 74 clientPreface = []byte(ClientPreface) 75 ) 76 77 type streamState int 78 79 // HTTP/2 stream states. 80 // 81 // See http://tools.ietf.org/html/rfc7540#section-5.1. 82 // 83 // For simplicity, the server code merges "reserved (local)" into 84 // "half-closed (remote)". This is one less state transition to track. 85 // The only downside is that we send PUSH_PROMISEs slightly less 86 // liberally than allowable. More discussion here: 87 // https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html 88 // 89 // "reserved (remote)" is omitted since the client code does not 90 // support server push. 91 const ( 92 stateIdle streamState = iota 93 stateOpen 94 stateHalfClosedLocal 95 stateHalfClosedRemote 96 stateClosed 97 ) 98 99 var stateName = [...]string{ 100 stateIdle: "Idle", 101 stateOpen: "Open", 102 stateHalfClosedLocal: "HalfClosedLocal", 103 stateHalfClosedRemote: "HalfClosedRemote", 104 stateClosed: "Closed", 105 } 106 107 func (st streamState) String() string { 108 return stateName[st] 109 } 110 111 // Setting is a setting parameter: which setting it is, and its value. 112 type Setting struct { 113 // ID is which setting is being set. 114 // See https://httpwg.org/specs/rfc7540.html#SettingFormat 115 ID SettingID 116 117 // Val is the value. 118 Val uint32 119 } 120 121 func (s Setting) String() string { 122 return fmt.Sprintf("[%v = %d]", s.ID, s.Val) 123 } 124 125 // Valid reports whether the setting is valid. 126 func (s Setting) Valid() error { 127 // Limits and error codes from 6.5.2 Defined SETTINGS Parameters 128 switch s.ID { 129 case SettingEnablePush: 130 if s.Val != 1 && s.Val != 0 { 131 return ConnectionError(ErrCodeProtocol) 132 } 133 case SettingInitialWindowSize: 134 if s.Val > 1<<31-1 { 135 return ConnectionError(ErrCodeFlowControl) 136 } 137 case SettingMaxFrameSize: 138 if s.Val < 16384 || s.Val > 1<<24-1 { 139 return ConnectionError(ErrCodeProtocol) 140 } 141 } 142 return nil 143 } 144 145 // A SettingID is an HTTP/2 setting as defined in 146 // https://httpwg.org/specs/rfc7540.html#iana-settings 147 type SettingID uint16 148 149 const ( 150 SettingHeaderTableSize SettingID = 0x1 151 SettingEnablePush SettingID = 0x2 152 SettingMaxConcurrentStreams SettingID = 0x3 153 SettingInitialWindowSize SettingID = 0x4 154 SettingMaxFrameSize SettingID = 0x5 155 SettingMaxHeaderListSize SettingID = 0x6 156 ) 157 158 var settingName = map[SettingID]string{ 159 SettingHeaderTableSize: "HEADER_TABLE_SIZE", 160 SettingEnablePush: "ENABLE_PUSH", 161 SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS", 162 SettingInitialWindowSize: "INITIAL_WINDOW_SIZE", 163 SettingMaxFrameSize: "MAX_FRAME_SIZE", 164 SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", 165 } 166 167 func (s SettingID) String() string { 168 if v, ok := settingName[s]; ok { 169 return v 170 } 171 return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s)) 172 } 173 174 // validWireHeaderFieldName reports whether v is a valid header field 175 // name (key). See httpguts.ValidHeaderName for the base rules. 176 // 177 // Further, http2 says: 178 // 179 // "Just as in HTTP/1.x, header field names are strings of ASCII 180 // characters that are compared in a case-insensitive 181 // fashion. However, header field names MUST be converted to 182 // lowercase prior to their encoding in HTTP/2. " 183 func validWireHeaderFieldName(v string) bool { 184 if len(v) == 0 { 185 return false 186 } 187 for _, r := range v { 188 if !httpguts.IsTokenRune(r) { 189 return false 190 } 191 if 'A' <= r && r <= 'Z' { 192 return false 193 } 194 } 195 return true 196 } 197 198 func httpCodeString(code int) string { 199 switch code { 200 case 200: 201 return "200" 202 case 404: 203 return "404" 204 } 205 return strconv.Itoa(code) 206 } 207 208 // from pkg io 209 type stringWriter interface { 210 WriteString(s string) (n int, err error) 211 } 212 213 // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed). 214 type closeWaiter chan struct{} 215 216 // Init makes a closeWaiter usable. 217 // It exists because so a closeWaiter value can be placed inside a 218 // larger struct and have the Mutex and Cond's memory in the same 219 // allocation. 220 func (cw *closeWaiter) Init() { 221 *cw = make(chan struct{}) 222 } 223 224 // Close marks the closeWaiter as closed and unblocks any waiters. 225 func (cw closeWaiter) Close() { 226 close(cw) 227 } 228 229 // Wait waits for the closeWaiter to become closed. 230 func (cw closeWaiter) Wait() { 231 <-cw 232 } 233 234 // bufferedWriter is a buffered writer that writes to w. 235 // Its buffered writer is lazily allocated as needed, to minimize 236 // idle memory usage with many connections. 237 type bufferedWriter struct { 238 _ incomparable 239 w io.Writer // immutable 240 bw *bufio.Writer // non-nil when data is buffered 241 } 242 243 func newBufferedWriter(w io.Writer) *bufferedWriter { 244 return &bufferedWriter{w: w} 245 } 246 247 // bufWriterPoolBufferSize is the size of bufio.Writer's 248 // buffers created using bufWriterPool. 249 // 250 // TODO: pick a less arbitrary value? this is a bit under 251 // (3 x typical 1500 byte MTU) at least. Other than that, 252 // not much thought went into it. 253 const bufWriterPoolBufferSize = 4 << 10 254 255 var bufWriterPool = sync.Pool{ 256 New: func() interface{} { 257 return bufio.NewWriterSize(nil, bufWriterPoolBufferSize) 258 }, 259 } 260 261 func (w *bufferedWriter) Available() int { 262 if w.bw == nil { 263 return bufWriterPoolBufferSize 264 } 265 return w.bw.Available() 266 } 267 268 func (w *bufferedWriter) Write(p []byte) (n int, err error) { 269 if w.bw == nil { 270 bw := bufWriterPool.Get().(*bufio.Writer) 271 bw.Reset(w.w) 272 w.bw = bw 273 } 274 return w.bw.Write(p) 275 } 276 277 func (w *bufferedWriter) Flush() error { 278 bw := w.bw 279 if bw == nil { 280 return nil 281 } 282 err := bw.Flush() 283 bw.Reset(nil) 284 bufWriterPool.Put(bw) 285 w.bw = nil 286 return err 287 } 288 289 func mustUint31(v int32) uint32 { 290 if v < 0 || v > 2147483647 { 291 panic("out of range") 292 } 293 return uint32(v) 294 } 295 296 // bodyAllowedForStatus reports whether a given response status code 297 // permits a body. See RFC 7230, section 3.3. 298 func bodyAllowedForStatus(status int) bool { 299 switch { 300 case status >= 100 && status <= 199: 301 return false 302 case status == 204: 303 return false 304 case status == 304: 305 return false 306 } 307 return true 308 } 309 310 type httpError struct { 311 _ incomparable 312 msg string 313 timeout bool 314 } 315 316 func (e *httpError) Error() string { return e.msg } 317 func (e *httpError) Timeout() bool { return e.timeout } 318 func (e *httpError) Temporary() bool { return true } 319 320 var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true} 321 322 type connectionStater interface { 323 ConnectionState() tls.ConnectionState 324 } 325 326 var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }} 327 328 type sorter struct { 329 v []string // owned by sorter 330 } 331 332 func (s *sorter) Len() int { return len(s.v) } 333 func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] } 334 func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] } 335 336 // Keys returns the sorted keys of h. 337 // 338 // The returned slice is only valid until s used again or returned to 339 // its pool. 340 func (s *sorter) Keys(h http.Header) []string { 341 keys := s.v[:0] 342 for k := range h { 343 keys = append(keys, k) 344 } 345 s.v = keys 346 sort.Sort(s) 347 return keys 348 } 349 350 func (s *sorter) SortStrings(ss []string) { 351 // Our sorter works on s.v, which sorter owns, so 352 // stash it away while we sort the user's buffer. 353 save := s.v 354 s.v = ss 355 sort.Sort(s) 356 s.v = save 357 } 358 359 // validPseudoPath reports whether v is a valid :path pseudo-header 360 // value. It must be either: 361 // 362 // - a non-empty string starting with '/' 363 // - the string '*', for OPTIONS requests. 364 // 365 // For now this is only used a quick check for deciding when to clean 366 // up Opaque URLs before sending requests from the Transport. 367 // See golang.org/issue/16847 368 // 369 // We used to enforce that the path also didn't start with "//", but 370 // Google's GFE accepts such paths and Chrome sends them, so ignore 371 // that part of the spec. See golang.org/issue/19103. 372 func validPseudoPath(v string) bool { 373 return (len(v) > 0 && v[0] == '/') || v == "*" 374 } 375 376 // incomparable is a zero-width, non-comparable type. Adding it to a struct 377 // makes that struct also non-comparable, and generally doesn't add 378 // any size (as long as it's first). 379 type incomparable [0]func()