github.com/soulteary/pocket-bookcase@v0.0.0-20240428065142-0b5a9a0fc98a/internal/cmd/server.go (about) 1 package cmd 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/soulteary/pocket-bookcase/internal/config" 8 "github.com/soulteary/pocket-bookcase/internal/http" 9 "github.com/soulteary/pocket-bookcase/internal/model" 10 "github.com/spf13/cobra" 11 "github.com/spf13/pflag" 12 ) 13 14 func newServerCommand() *cobra.Command { 15 cmd := &cobra.Command{ 16 Use: "server", 17 Short: "Starts the Shiori webserver", 18 Long: "Serves the Shiori web interface and API.", 19 Run: newServerCommandHandler(), 20 } 21 22 cmd.Flags().IntP("port", "p", 8080, "Port used by the server") 23 cmd.Flags().StringP("address", "a", "", "Address the server listens to") 24 cmd.Flags().StringP("webroot", "r", "/", "Root path that used by server") 25 cmd.Flags().Bool("access-log", false, "Print out a non-standard access log") 26 cmd.Flags().Bool("serve-web-ui", true, "Serve static files from the webroot path") 27 cmd.Flags().String("secret-key", "", "Secret key used for encrypting session data") 28 29 return cmd 30 } 31 32 func setIfFlagChanged(flagName string, flags *pflag.FlagSet, cfg *config.Config, fn func(cfg *config.Config)) { 33 if flags.Changed(flagName) { 34 fn(cfg) 35 } 36 } 37 38 func newServerCommandHandler() func(cmd *cobra.Command, args []string) { 39 return func(cmd *cobra.Command, args []string) { 40 ctx := context.Background() 41 42 // Get flags values 43 port, _ := cmd.Flags().GetInt("port") 44 address, _ := cmd.Flags().GetString("address") 45 rootPath, _ := cmd.Flags().GetString("webroot") 46 accessLog, _ := cmd.Flags().GetBool("access-log") 47 serveWebUI, _ := cmd.Flags().GetBool("serve-web-ui") 48 secretKey, _ := cmd.Flags().GetBytesHex("secret-key") 49 50 cfg, dependencies := initShiori(ctx, cmd) 51 52 // Validate root path 53 if rootPath == "" { 54 rootPath = "/" 55 } 56 57 if !strings.HasPrefix(rootPath, "/") { 58 rootPath = "/" + rootPath 59 } 60 61 if !strings.HasSuffix(rootPath, "/") { 62 rootPath += "/" 63 } 64 65 // Override configuration from flags if needed 66 setIfFlagChanged("port", cmd.Flags(), cfg, func(cfg *config.Config) { 67 cfg.Http.Port = port 68 }) 69 setIfFlagChanged("address", cmd.Flags(), cfg, func(cfg *config.Config) { 70 cfg.Http.Address = address + ":" 71 }) 72 setIfFlagChanged("webroot", cmd.Flags(), cfg, func(cfg *config.Config) { 73 cfg.Http.RootPath = rootPath 74 }) 75 setIfFlagChanged("access-log", cmd.Flags(), cfg, func(cfg *config.Config) { 76 cfg.Http.AccessLog = accessLog 77 }) 78 setIfFlagChanged("serve-web-ui", cmd.Flags(), cfg, func(cfg *config.Config) { 79 cfg.Http.ServeWebUI = serveWebUI 80 }) 81 setIfFlagChanged("secret-key", cmd.Flags(), cfg, func(cfg *config.Config) { 82 cfg.Http.SecretKey = secretKey 83 }) 84 85 dependencies.Log.Infof("Starting Shiori v%s", model.BuildVersion) 86 87 server, err := http.NewHttpServer(dependencies.Log).Setup(cfg, dependencies) 88 if err != nil { 89 dependencies.Log.WithError(err).Fatal("error setting up server") 90 } 91 92 if err := server.Start(ctx); err != nil { 93 dependencies.Log.WithError(err).Fatal("error starting server") 94 } 95 dependencies.Log.WithField("addr", address).Debug("started http server") 96 97 server.WaitStop(ctx) 98 } 99 }