package http import ( "context" "errors" "fmt" "ims/app/http/middleware" "ims/app/http/routes" "ims/util/log" "net/http" "zestack.dev/env" "zestack.dev/slim" ) var ( started chan struct{} exit chan chan error ) func init() { started = make(chan struct{}) exit = make(chan chan error) } func Start(ctx context.Context) error { select { case <-started: return errors.New("app: server already started") default: close(started) } app := createKernel() srv := createServer(app) routes.Init(app) go func() { if srvErr := app.StartServer(srv); srvErr != nil { log.Error("encountered an error while serving listener: ", srvErr) } }() go func() { // 监听停止命令,停止网络服务 errChan := <-exit // 停止 slim 应用 errChan <- app.Close() }() return nil } func createKernel() *slim.Slim { app := slim.New() app.Debug = !env.IsEnv("prod") app.Logger = log.Default() app.ErrorHandler = middleware.ErrorHandler app.ResetRouterCreator(func(s *slim.Slim) slim.Router { return slim.NewRouter(slim.RouterConfig{ RoutingTrailingSlash: true, }) }) app.Use(slim.Logging()) app.Use(slim.Recovery()) app.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: env.List("CORS_ALLOW_ORIGINS"), AllowMethods: env.List("CORS_ALLOW_METHODS"), AllowHeaders: env.List("CORS_ALLOW_HEADERS"), AllowCredentials: env.Bool("CORS_ALLOW_CREDENTIALS"), ExposeHeaders: env.List("CORS_EXPOSE_HEADERS"), MaxAge: env.Int("CORS_MAX_AGE"), })) return app } func createServer(app *slim.Slim) *http.Server { // TODO 支持 TLSConfig 配置 return &http.Server{ Addr: fmt.Sprintf("%s:%d", env.String("SERVER_ADDR"), env.Int("SERVER_PORT", 1234)), Handler: app, ReadTimeout: env.Duration("HTTP_READ_TIMEOUT", 0), ReadHeaderTimeout: env.Duration("HTTP_READ_HEADER_TIMEOUT", 0), WriteTimeout: env.Duration("HTTP_WRITE_TIMEOUT", 0), IdleTimeout: env.Duration("HTTP_IDLE_TIMEOUT", 0), MaxHeaderBytes: env.Int("HTTP_MAX_HEADER_BYTES", http.DefaultMaxHeaderBytes), } } func Stop() error { select { case <-started: errCh := make(chan error) exit <- errCh return <-errCh default: return nil } }