implemented http server
This commit is contained in:
+64
-21
@@ -5,17 +5,76 @@ import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"serveg/internal/log"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
// TODO: add example config file
|
||||
type Shares []*SharedLocation
|
||||
|
||||
type Config struct {
|
||||
Addr string `toml:"address"`
|
||||
Addr string `toml:"address"`
|
||||
MaxUpload int64 `toml:"max_upload"`
|
||||
// sorted by Url in reverse to allow this pattern:
|
||||
// shared/private
|
||||
// shared/
|
||||
Share Shares `toml:"share"`
|
||||
}
|
||||
|
||||
func ReadConfig(path string) (*Config, error) {
|
||||
var config = DefaultConfig()
|
||||
var confLogger = log.LoggerContext{Name: "config"}
|
||||
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
Addr: "127.0.0.1:8080",
|
||||
MaxUpload: 4 * 1024 * 1024 * 1024, // 4 GB
|
||||
}
|
||||
}
|
||||
|
||||
func ParseOrCreateConfig(confPath string) (*Config, error) {
|
||||
confLogger.Info("reading config file ", confPath)
|
||||
conf, err := readConfig(confPath)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
confLogger.Warn("config doesn't exist, creating default")
|
||||
conf = defaultConfig()
|
||||
err = writeConfig(conf, confPath)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
confLogger.Info("address: ", conf.Addr)
|
||||
confLogger.Info("max_upload: ", conf.MaxUpload)
|
||||
confDir := filepath.Dir(confPath)
|
||||
sharesByUrl := make(map[string]*SharedLocation, len(conf.Share))
|
||||
for _, sh := range conf.Share {
|
||||
if err = sh.normalize(confDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
confLogger.Info(sh)
|
||||
|
||||
if other, exists := sharesByUrl[sh.Url]; exists {
|
||||
return nil, fmt.Errorf("duplicate share url: %v and %v", other, sh)
|
||||
}
|
||||
sharesByUrl[sh.Url] = sh
|
||||
|
||||
if err = sh.mkdir(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// reverse sort by Url
|
||||
slices.SortFunc(conf.Share, func(a, b *SharedLocation) int {
|
||||
return strings.Compare(b.Url, a.Url) // reverse
|
||||
})
|
||||
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
func readConfig(path string) (*Config, error) {
|
||||
var config = defaultConfig()
|
||||
tomlMeta, err := toml.DecodeFile(path, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -25,26 +84,10 @@ func ReadConfig(path string) (*Config, error) {
|
||||
if undecodedKeys := tomlMeta.Undecoded(); len(undecodedKeys) > 0 {
|
||||
return nil, fmt.Errorf("%s: unknown keys: %v", path, undecodedKeys)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Addr: "127.0.0.1:8080",
|
||||
}
|
||||
}
|
||||
|
||||
func ParseOrCreateConfig(path string) (*Config, error) {
|
||||
config, err := ReadConfig(path)
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return config, err // either a parsed config, or a real error
|
||||
}
|
||||
config = DefaultConfig()
|
||||
return config, WriteConfig(config, path)
|
||||
}
|
||||
|
||||
func WriteConfig(config *Config, path string) (err error) {
|
||||
func writeConfig(config *Config, path string) (err error) {
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user