ServeHTTP is the entry point for all HTTP requests.
(w http.ResponseWriter, r *http.Request)
| 309 | |
| 310 | // ServeHTTP is the entry point for all HTTP requests. |
| 311 | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 312 | start := time.Now() |
| 313 | |
| 314 | // If there are listener wrappers that process tls connections but don't return a *tls.Conn, this field will be nil. |
| 315 | if r.TLS == nil { |
| 316 | if tlsConnStateFunc, ok := r.Context().Value(tlsConnectionStateFuncCtxKey).(func() *tls.ConnectionState); ok { |
| 317 | r.TLS = tlsConnStateFunc() |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | // enable full-duplex for HTTP/1, ensuring the entire |
| 322 | // request body gets consumed before writing the response |
| 323 | if s.EnableFullDuplex && r.ProtoMajor == 1 { |
| 324 | if err := http.NewResponseController(w).EnableFullDuplex(); err != nil { //nolint:bodyclose |
| 325 | if c := s.logger.Check(zapcore.WarnLevel, "failed to enable full duplex"); c != nil { |
| 326 | c.Write(zap.Error(err)) |
| 327 | } |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | // set the Server header |
| 332 | h := w.Header() |
| 333 | h["Server"] = serverHeader |
| 334 | |
| 335 | // advertise HTTP/3, if enabled |
| 336 | if s.h3server != nil && r.ProtoMajor < 3 { |
| 337 | if err := s.h3server.SetQUICHeaders(h); err != nil { |
| 338 | if c := s.logger.Check(zapcore.ErrorLevel, "setting HTTP/3 Alt-Svc header"); c != nil { |
| 339 | c.Write(zap.Error(err)) |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | // prepare internals of the request for the handler pipeline |
| 345 | repl := caddy.NewReplacer() |
| 346 | r = PrepareRequest(r, repl, w, s) |
| 347 | |
| 348 | // clone the request for logging purposes before it enters any handler chain; |
| 349 | // this is necessary to capture the original request in case it gets modified |
| 350 | // during handling (cloning the request and using .WithLazy is considerably |
| 351 | // faster than using .With, which will JSON-encode the request immediately) |
| 352 | shouldLogCredentials := s.Logs != nil && s.Logs.ShouldLogCredentials |
| 353 | loggableReq := zap.Object("request", LoggableHTTPRequest{ |
| 354 | Request: r.Clone(r.Context()), |
| 355 | ShouldLogCredentials: shouldLogCredentials, |
| 356 | }) |
| 357 | errLog := s.errorLogger.WithLazy(loggableReq) |
| 358 | |
| 359 | var duration time.Duration |
| 360 | |
| 361 | if s.shouldLogRequest(r) { |
| 362 | wrec := NewResponseRecorder(w, nil, nil) |
| 363 | w = wrec |
| 364 | |
| 365 | // wrap the request body in a LengthReader |
| 366 | // so we can track the number of bytes read from it |
| 367 | var bodyReader *lengthReader |
| 368 | if r.Body != nil { |
nothing calls this directly
no test coverage detected