package sub import ( "context" "crypto/tls" "io" "net" "net/http" "strconv" "time" "github.com/alireza0/s-ui/config" "github.com/alireza0/s-ui/logger" "github.com/alireza0/s-ui/middleware" "github.com/alireza0/s-ui/network" "github.com/alireza0/s-ui/service" "github.com/gin-gonic/gin" ) type Server struct { httpServer *http.Server listener net.Listener ctx context.Context cancel context.CancelFunc service.SettingService } func NewServer() *Server { ctx, cancel := context.WithCancel(context.Background()) return &Server{ ctx: ctx, cancel: cancel, } } func (s *Server) initRouter() (*gin.Engine, error) { if config.IsDebug() { gin.SetMode(gin.DebugMode) } else { gin.DefaultWriter = io.Discard gin.DefaultErrorWriter = io.Discard gin.SetMode(gin.ReleaseMode) } engine := gin.Default() subPath, err := s.SettingService.GetSubPath() if err != nil { return nil, err } subDomain, err := s.SettingService.GetSubDomain() if err != nil { return nil, err } if subDomain != "" { engine.Use(middleware.DomainValidator(subDomain)) } g := engine.Group(subPath) NewSubHandler(g) return engine, nil } func (s *Server) Start() (err error) { //This is an anonymous function, no function name defer func() { if err != nil { s.Stop() } }() engine, err := s.initRouter() if err != nil { return err } certFile, err := s.SettingService.GetSubCertFile() if err != nil { return err } keyFile, err := s.SettingService.GetSubKeyFile() if err != nil { return err } listen, err := s.SettingService.GetSubListen() if err != nil { return err } port, err := s.SettingService.GetSubPort() if err != nil { return err } listenAddr := net.JoinHostPort(listen, strconv.Itoa(port)) listener, err := net.Listen("tcp", listenAddr) if err != nil { return err } if certFile != "" || keyFile != "" { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { listener.Close() return err } c := &tls.Config{ Certificates: []tls.Certificate{cert}, } listener = network.NewAutoHttpsListener(listener) listener = tls.NewListener(listener, c) } if certFile != "" || keyFile != "" { logger.Info("Sub server run https on", listener.Addr()) } else { logger.Info("Sub server run http on", listener.Addr()) } s.listener = listener s.httpServer = &http.Server{ Handler: engine, } go func() { s.httpServer.Serve(listener) }() return nil } func (s *Server) Stop() error { var err error if s.httpServer != nil { shutdownCtx, cancelShutdown := context.WithTimeout(context.Background(), 30*time.Second) err = s.httpServer.Shutdown(shutdownCtx) cancelShutdown() if err != nil { s.cancel() if s.listener != nil { _ = s.listener.Close() } return err } } else if s.listener != nil { err = s.listener.Close() if err != nil { s.cancel() return err } } s.cancel() return nil } func (s *Server) GetCtx() context.Context { return s.ctx }