package server import ( "errors" "fmt" "net/http" "time" ) // HTTP server configuration constants. const ( HTTPReadTimeout = 30 * time.Second // HTTPReadHeaderTimeout bounds the request-header read on its own, // short, so a slowloris client dribbling headers is dropped well // before it ties up a connection for the whole ReadTimeout window. HTTPReadHeaderTimeout = 10 * time.Second HTTPWriteTimeout = 60 * time.Second // HTTPIdleTimeout bounds how long an idle keep-alive connection is // held open, so idle connections cannot accumulate without limit on a // service targeting high concurrency. HTTPIdleTimeout = 120 * time.Second HTTPMaxHeaderBytes = 8 << 10 // 8KB ) // newHTTPServer builds the http.Server with the hardening timeouts and // limits applied. It is separate from serveUntilShutdown so the // configuration can be asserted in a test without binding a listener. func (s *Server) newHTTPServer() *http.Server { return &http.Server{ Addr: fmt.Sprintf(":%d", s.config.Port), ReadTimeout: HTTPReadTimeout, ReadHeaderTimeout: HTTPReadHeaderTimeout, WriteTimeout: HTTPWriteTimeout, IdleTimeout: HTTPIdleTimeout, MaxHeaderBytes: HTTPMaxHeaderBytes, Handler: s, } } func (s *Server) serveUntilShutdown() { s.httpServer = s.newHTTPServer() s.SetupRoutes() s.log.Info("http begin listen", "listenaddr", s.httpServer.Addr) err := s.httpServer.ListenAndServe() if err != nil && !errors.Is(err, http.ErrServerClosed) { s.log.Error("listen error", "error", err) if s.cancelFunc != nil { s.cancelFunc() } } } // ServeHTTP implements http.Handler. func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.router.ServeHTTP(w, r) }