Start starts the http server. cancel is called in case server failed to start, but it happened asynchronously. It should cancel the upstream context.
(cancel context.CancelFunc, router *Router)
| 27 | // Start starts the http server. cancel is called in case server failed to start, but it happened |
| 28 | // asynchronously. It should cancel the upstream context. |
| 29 | func Start(cancel context.CancelFunc, router *Router) (*Server, error) { |
| 30 | l, err := reuseport.Listen(router.config.Network, router.config.Bind, router.config.SocketReusePort) |
| 31 | if err != nil { |
| 32 | cancel() |
| 33 | return nil, fmt.Errorf("can't start server: %w", err) |
| 34 | } |
| 35 | |
| 36 | if router.config.MaxClients > 0 { |
| 37 | l = netutil.LimitListener(l, router.config.MaxClients) |
| 38 | } |
| 39 | |
| 40 | errLogger := slog.NewLogLogger( |
| 41 | slog.With("source", "http_server").Handler(), |
| 42 | slog.LevelError, |
| 43 | ) |
| 44 | |
| 45 | addr := l.Addr() |
| 46 | |
| 47 | srv := &http.Server{ |
| 48 | Handler: router, |
| 49 | ReadTimeout: router.config.ReadRequestTimeout, |
| 50 | MaxHeaderBytes: maxHeaderBytes, |
| 51 | ErrorLog: errLogger, |
| 52 | } |
| 53 | |
| 54 | if router.config.KeepAliveTimeout > 0 { |
| 55 | srv.IdleTimeout = router.config.KeepAliveTimeout |
| 56 | } else { |
| 57 | srv.SetKeepAlivesEnabled(false) |
| 58 | } |
| 59 | |
| 60 | go func() { |
| 61 | slog.Info(fmt.Sprintf("Starting server at %s", router.config.Bind)) |
| 62 | |
| 63 | if err := srv.Serve(l); err != nil && err != http.ErrServerClosed { |
| 64 | slog.Error(err.Error(), "source", "http_server") |
| 65 | } |
| 66 | |
| 67 | cancel() |
| 68 | }() |
| 69 | |
| 70 | return &Server{ |
| 71 | router: router, |
| 72 | server: srv, |
| 73 | Addr: addr, |
| 74 | }, nil |
| 75 | } |
| 76 | |
| 77 | // Shutdown gracefully shuts down the server |
| 78 | func (s *Server) Shutdown(ctx context.Context) { |