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  }