package service import ( "context" "net" "strings" "time" "github.com/sirupsen/logrus" "github.com/valyala/fasthttp" "github.com/authelia/authelia/v4/internal/server" ) func ProvisionServer(ctx Context) (service Provider, err error) { var ( s *fasthttp.Server listener net.Listener paths []string isTLS bool ) switch s, listener, paths, isTLS, err = server.New(ctx.GetConfiguration(), ctx.GetProviders()); { case err != nil: return nil, err case s != nil && listener != nil: service = NewBaseServer("main", s, listener, paths, isTLS, ctx.GetLogger()) default: return nil, nil } return service, nil } func ProvisionServerMetrics(ctx Context) (service Provider, err error) { var ( s *fasthttp.Server listener net.Listener paths []string isTLS bool ) switch s, listener, paths, isTLS, err = server.NewMetrics(ctx.GetConfiguration(), ctx.GetProviders()); { case err != nil: return nil, err case s != nil && listener != nil: service = NewBaseServer("metrics", s, listener, paths, isTLS, ctx.GetLogger()) default: return nil, nil } return service, nil } // NewBaseServer creates a new Server with the appropriate logger etc. func NewBaseServer(name string, server *fasthttp.Server, listener net.Listener, paths []string, isTLS bool, log *logrus.Entry) (service *Server) { return &Server{ name: name, server: server, listener: listener, paths: paths, isTLS: isTLS, log: log.WithFields(map[string]any{logFieldService: serviceTypeServer, serviceTypeServer: name}), } } // Server is a Provider which runs a web server. type Server struct { name string server *fasthttp.Server paths []string isTLS bool listener net.Listener log *logrus.Entry } // ServiceType returns the service type for this service, which is always 'server'. func (service *Server) ServiceType() string { return serviceTypeServer } // ServiceName returns the individual name for this service. func (service *Server) ServiceName() string { return service.name } // Run the Server. func (service *Server) Run() (err error) { defer func() { if r := recover(); r != nil { service.log.WithError(recoverErr(r)).Error("Critical error caught (recovered)") } }() service.log.Infof(fmtLogServerListening, connectionType(service.isTLS), service.listener.Addr().String(), strings.Join(service.paths, "' and '")) if err = service.server.Serve(service.listener); err != nil { service.log.WithError(err).Error("Error returned attempting to serve requests") return err } return nil } // Shutdown the Server. func (service *Server) Shutdown() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() if err := service.server.ShutdownWithContext(ctx); err != nil { service.log.WithError(err).Error("Error occurred during shutdown") } } // Log returns the *logrus.Entry of the Server. func (service *Server) Log() *logrus.Entry { return service.log }