[server] Use koanf for server config

This commit is contained in:
Abhishek Shroff
2025-05-15 12:37:27 +05:30
parent e19849ce7e
commit 60e3838bab
5 changed files with 73 additions and 83 deletions

View File

@@ -2,6 +2,7 @@ package command
import (
"errors"
"fmt"
"os"
"path"
"strings"
@@ -36,8 +37,8 @@ func SetupCommand() {
flags := rootCmd.PersistentFlags()
// Flags only. Not part of config file
flags.StringP("workdir", "W", "", "Set working directory")
flags.StringP("config-file", "c", "config.yml", "Set working directory")
flags.StringP("workdir", "W", "", "Working Directory")
flags.StringP("config-file", "c", "config.yml", "Config File Path")
flags.Bool("debug", false, "Debug mode")
flags.MarkHidden("debug")
@@ -76,7 +77,9 @@ func SetupCommand() {
if !f.Changed {
return "", ""
}
return strings.ReplaceAll(f.Name, "_", "."), posflag.FlagVal(cmd.Flags(), f)
k, v := strings.ReplaceAll(f.Name, "_", "."), posflag.FlagVal(cmd.Flags(), f)
fmt.Printf("%s: %v\n", k, v)
return k, v
}), nil); err != nil {
logrus.Fatalf("Unable to load flags: %v", err)
}
@@ -91,6 +94,7 @@ func SetupCommand() {
db.Cfg = cfg.DB
storage.Cfg = cfg.Storage
serve.Cfg = cfg.Server
}
defer func() {

View File

@@ -1,6 +1,7 @@
package command
import (
"github.com/shroff/phylum/server/internal/command/serve"
"github.com/shroff/phylum/server/internal/core/db"
"github.com/shroff/phylum/server/internal/core/storage"
)
@@ -19,15 +20,15 @@ var defaultConfig = Config{
Storage: storage.Config{
Location: "storage",
},
Server: ServerConfig{
Server: serve.Config{
Host: "",
Port: 2448,
WebAppSrc: "web",
PublinkPath: "/publink",
WebDAVPath: "/webdav",
CORS: CORSConfig{
CORS: serve.CORSConfig{
Enabled: false,
Orifins: []string{"*"},
Origins: []string{"*"},
},
},
}
@@ -36,19 +37,5 @@ type Config struct {
Debug bool `koanf:"debug"`
DB db.Config `koanf:"db"`
Storage storage.Config `koanf:"storage"`
Server ServerConfig `koanf:"server"`
}
type ServerConfig struct {
Host string `koanf:"host"`
Port int `koanf:"port"`
WebAppSrc string `koanf:"web_app_src"`
PublinkPath string `koanf:"publink_path"`
WebDAVPath string `koanf:"webdav_path"`
CORS CORSConfig `koanf:"cors"`
}
type CORSConfig struct {
Enabled bool `koanf:"enabled"`
Orifins []string `koanf:"origins"`
Server serve.Config `koanf:"server"`
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"net/http"
"path"
"strconv"
"time"
"github.com/fvbock/endless"
@@ -15,76 +16,58 @@ import (
"github.com/shroff/phylum/server/internal/core/fs"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const trashRetainDuration = 30 * 24 * time.Hour
var Cfg Config
func SetupCommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "serve",
Short: "Run the server",
GroupID: "server",
Run: func(cmd *cobra.Command, args []string) {
config := viper.Sub("server")
flags := cmd.Flags()
// TODO: Hack. flag bindings don't work in viper for nested keys
config.BindPFlag("host", flags.Lookup("host"))
config.BindPFlag("port", flags.Lookup("port"))
config.BindPFlag("cors.enabled", flags.Lookup("cors-enabled"))
config.BindPFlag("cors.origins", flags.Lookup("cors-origins"))
config.BindPFlag("log_body", flags.Lookup("log-body"))
config.BindPFlag("web_app_src", flags.Lookup("web-app-src"))
config.BindPFlag("publink_path", flags.Lookup("publink-path"))
config.BindPFlag("webdav_path", flags.Lookup("webdav-path"))
if !viper.GetBool("debug") {
gin.SetMode(gin.ReleaseMode)
}
engine := createEngine(config)
webdav.SetupHandler(engine.Group(config.GetString("webdav_path")))
apiv1.Setup(engine.Group("/api/v1"))
publink.Setup(engine.Group(config.GetString("publink_path")))
webAppSrcDir := config.GetString("web_app_src")
if webAppSrcDir != "" {
setupWebApp(engine, webAppSrcDir)
}
setupTrashCompactor()
listen := config.GetString("host") + ":" + config.GetString("port")
server := endless.NewServer(listen, engine)
server.BeforeBegin = func(addr string) {
logrus.Info("Listening on " + addr)
}
if err := server.ListenAndServe(); err != nil {
logrus.Fatal(err.Error())
}
},
}
flags := cmd.Flags()
flags.String("host", "", "Server Host")
flags.String("port", "2448", "Server Port")
flags.Bool("cors-enabled", false, "Enable CORS")
flags.StringSlice("cors-origins", []string{"*"}, "CORS origins")
flags.Bool("log-body", false, "Log Response Body (Must be used with --debug)")
flags.String("web-app-src", "web", "Web App Source Directory")
flags.String("publink-path", "/publink", "Public Share path prefix")
flags.String("webdav-path", "/webdav", "WebDAV path prefix")
flags.Bool("db_trace", false, "Trace Database Queries")
flags.MarkHidden("db_trace")
// Must be specified otherwise env variables won't be parsed
viper.SetDefault("server.host", "")
viper.SetDefault("server.port", "2448")
viper.SetDefault("server.log_body", false)
viper.SetDefault("server.cors.enabled", false)
viper.SetDefault("server.cors.origins", []string{"*"})
viper.SetDefault("server.web_app_src", "web")
viper.SetDefault("server.publink_path", "/publink")
viper.SetDefault("server.webdav_path", "/webdav")
flags.String("server_host", "", "Server Host")
flags.String("server_port", "", "Server Port")
flags.String("server_webappsrc", "", "Web App Source Directory")
flags.String("server_publinkpath", "", "Public Share path prefix")
flags.String("server_webdavpath", "", "WebDAV path prefix")
flags.Bool("server_cors_enabled", false, "Enable CORS")
flags.StringSlice("server_cors_origins", nil, "CORS origins")
flags.Bool("server_logbody", false, "Log Response Body (Must be used with --debug)")
cmd.Run = func(cmd *cobra.Command, args []string) {
if !Cfg.Debug {
gin.SetMode(gin.ReleaseMode)
}
engine := createEngine()
webdav.SetupHandler(engine.Group(Cfg.WebDAVPath))
apiv1.Setup(engine.Group("/api/v1"))
publink.Setup(engine.Group(Cfg.PublinkPath))
if Cfg.WebAppSrc != "" {
setupWebApp(engine, Cfg.WebAppSrc)
}
setupTrashCompactor()
listen := Cfg.Host + ":" + strconv.Itoa(Cfg.Port)
server := endless.NewServer(listen, engine)
server.BeforeBegin = func(addr string) {
logrus.Info("Listening on " + addr)
}
if err := server.ListenAndServe(); err != nil {
logrus.Fatal(err.Error())
}
}
return cmd
}

View File

@@ -0,0 +1,17 @@
package serve
type Config struct {
Host string `koanf:"host"`
Port int `koanf:"port"`
WebAppSrc string `koanf:"webappsrc"`
PublinkPath string `koanf:"publinkpath"`
WebDAVPath string `koanf:"webdavpath"`
CORS CORSConfig `koanf:"cors"`
Debug bool `koanf:"debug"`
LogBody bool `koanf:"logbody"`
}
type CORSConfig struct {
Enabled bool `koanf:"enabled"`
Origins []string `koanf:"origins"`
}

View File

@@ -9,11 +9,10 @@ import (
"github.com/gin-gonic/gin"
"github.com/shroff/phylum/server/internal/core/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
// func createEngine(logBody bool, corsEnabled bool, corsOrigins []string) *gin.Engine {
func createEngine(config *viper.Viper) *gin.Engine {
func createEngine() *gin.Engine {
engine := gin.New()
engine.Use(gin.Logger(), gin.CustomRecovery(func(c *gin.Context, err any) {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
@@ -22,12 +21,12 @@ func createEngine(config *viper.Viper) *gin.Engine {
"msg": "Internal Server Error",
})
}))
if config.GetBool("log_body") {
if Cfg.LogBody {
engine.Use(logBodyMiddleware)
}
if config.GetBool("cors.enabled") {
origins := config.GetStringSlice("cors.origins")
if Cfg.CORS.Enabled {
origins := Cfg.CORS.Origins
logrus.Info("Enabling cors (" + strings.Join(origins, ", ") + ")")
engine.Use(cors.New(cors.Config{
AllowOrigins: origins,