Run will start a HTTP server listening on the provided listener and serving the provided handler. This call is blocking and the run is cancelled when the input context is cancelled, the listener is closed upon return. The Run function can be configured further by passing a variety of options.
( ctx context.Context, logger *slog.Logger, listener net.Listener, handler http.Handler, options ...RunOption, )
| 87 | // |
| 88 | // The Run function can be configured further by passing a variety of options. |
| 89 | func Run( |
| 90 | ctx context.Context, |
| 91 | logger *slog.Logger, |
| 92 | listener net.Listener, |
| 93 | handler http.Handler, |
| 94 | options ...RunOption, |
| 95 | ) error { |
| 96 | s := &runner{ |
| 97 | shutdownTimeout: DefaultShutdownTimeout, |
| 98 | readHeaderTimeout: DefaultReadHeaderTimeout, |
| 99 | } |
| 100 | for _, option := range options { |
| 101 | option(s) |
| 102 | } |
| 103 | protocols := new(http.Protocols) |
| 104 | protocols.SetHTTP1(true) |
| 105 | protocols.SetHTTP2(true) |
| 106 | protocols.SetUnencryptedHTTP2(!s.disableH2C) |
| 107 | httpServer := &http.Server{ |
| 108 | Handler: handler, |
| 109 | ReadHeaderTimeout: s.readHeaderTimeout, |
| 110 | ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError), |
| 111 | TLSConfig: s.tlsConfig, |
| 112 | Protocols: protocols, |
| 113 | IdleTimeout: DefaultIdleTimeout, |
| 114 | } |
| 115 | |
| 116 | eg, ctx := errgroup.WithContext(ctx) |
| 117 | eg.Go(func() error { |
| 118 | return httpServe(httpServer, listener) |
| 119 | }) |
| 120 | eg.Go(func() error { |
| 121 | <-ctx.Done() |
| 122 | start := time.Now() |
| 123 | logger.Info("shutdown_starting", slog.Duration("shutdown_timeout", s.shutdownTimeout)) |
| 124 | defer func() { |
| 125 | logger.Info("shutdown_finished", slog.Duration("duration", time.Since(start))) |
| 126 | }() |
| 127 | if s.shutdownTimeout != 0 { |
| 128 | ctx, cancel := context.WithTimeout(context.Background(), s.shutdownTimeout) |
| 129 | defer cancel() |
| 130 | return httpServer.Shutdown(ctx) |
| 131 | } |
| 132 | return httpServer.Close() |
| 133 | }) |
| 134 | |
| 135 | logger.Info( |
| 136 | "starting", |
| 137 | slog.String("address", listener.Addr().String()), |
| 138 | slog.Duration("shutdown_timeout", s.shutdownTimeout), |
| 139 | slog.Bool("tls", s.tlsConfig != nil), |
| 140 | ) |
| 141 | if err := eg.Wait(); err != http.ErrServerClosed { |
| 142 | return err |
| 143 | } |
| 144 | return nil |
| 145 | } |
| 146 |