From 7edac1334d849de87ea2415938a4a8ea7fa261a9 Mon Sep 17 00:00:00 2001 From: MrMelon54 Date: Wed, 8 May 2024 01:10:58 +0100 Subject: [PATCH] Add base server --- backend.go | 50 +++++++++++++++++++++++++++++++ cmd/daisy/main.go | 19 ++++++++++++ cmd/daisy/serve.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 13 ++++++++ go.sum | 27 +++++++++++++++++ server.go | 27 +++++++++++++++++ 6 files changed, 211 insertions(+) create mode 100644 backend.go create mode 100644 cmd/daisy/main.go create mode 100644 cmd/daisy/serve.go create mode 100644 go.sum create mode 100644 server.go diff --git a/backend.go b/backend.go new file mode 100644 index 0000000..4ca4bc6 --- /dev/null +++ b/backend.go @@ -0,0 +1,50 @@ +package daisy + +import ( + "context" + "github.com/emersion/go-vcard" + "github.com/emersion/go-webdav/carddav" +) + +type Backend struct { +} + +func (b *Backend) AddressbookHomeSetPath(ctx context.Context) (string, error) { + //TODO implement me + panic("implement me") +} + +func (b *Backend) AddressBook(ctx context.Context) (*carddav.AddressBook, error) { + //TODO implement me + panic("implement me") +} + +func (b *Backend) GetAddressObject(ctx context.Context, path string, req *carddav.AddressDataRequest) (*carddav.AddressObject, error) { + //TODO implement me + panic("implement me") +} + +func (b *Backend) ListAddressObjects(ctx context.Context, req *carddav.AddressDataRequest) ([]carddav.AddressObject, error) { + //TODO implement me + panic("implement me") +} + +func (b *Backend) QueryAddressObjects(ctx context.Context, query *carddav.AddressBookQuery) ([]carddav.AddressObject, error) { + //TODO implement me + panic("implement me") +} + +func (b *Backend) PutAddressObject(ctx context.Context, path string, card vcard.Card, opts *carddav.PutAddressObjectOptions) (loc string, err error) { + //TODO implement me + panic("implement me") +} + +func (b *Backend) DeleteAddressObject(ctx context.Context, path string) error { + //TODO implement me + panic("implement me") +} + +func (b *Backend) CurrentUserPrincipal(ctx context.Context) (string, error) { + //TODO implement me + panic("implement me") +} diff --git a/cmd/daisy/main.go b/cmd/daisy/main.go new file mode 100644 index 0000000..f0b4be5 --- /dev/null +++ b/cmd/daisy/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "context" + "flag" + "github.com/google/subcommands" + "os" +) + +func main() { + subcommands.Register(subcommands.HelpCommand(), "") + subcommands.Register(subcommands.FlagsCommand(), "") + subcommands.Register(subcommands.CommandsCommand(), "") + subcommands.Register(&serveCmd{}, "") + + flag.Parse() + ctx := context.Background() + os.Exit(int(subcommands.Execute(ctx))) +} diff --git a/cmd/daisy/serve.go b/cmd/daisy/serve.go new file mode 100644 index 0000000..14c35db --- /dev/null +++ b/cmd/daisy/serve.go @@ -0,0 +1,75 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "github.com/1f349/daisy" + "github.com/1f349/violet/utils" + "github.com/google/subcommands" + "github.com/mrmelon54/exit-reload" + "log" + "os" + "path/filepath" +) + +type serveCmd struct{ configPath string } + +func (s *serveCmd) Name() string { return "serve" } + +func (s *serveCmd) Synopsis() string { return "Serve contacts service" } + +func (s *serveCmd) SetFlags(f *flag.FlagSet) { + f.StringVar(&s.configPath, "conf", "", "/path/to/config.json : path to the config file") +} + +func (s *serveCmd) Usage() string { + return `serve [-conf ] + Serve contacts service using information from the config file +` +} + +func (s *serveCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...any) subcommands.ExitStatus { + log.Println("[Daisy] Starting...") + + if s.configPath == "" { + log.Println("[Daisy] Error: config flag is missing") + return subcommands.ExitUsageError + } + + openConf, err := os.Open(s.configPath) + if err != nil { + if os.IsNotExist(err) { + log.Println("[Daisy] Error: missing config file") + } else { + log.Println("[Daisy] Error: open config file: ", err) + } + return subcommands.ExitFailure + } + + var config daisy.Conf + err = json.NewDecoder(openConf).Decode(&config) + if err != nil { + log.Println("[Daisy] Error: invalid config file: ", err) + return subcommands.ExitFailure + } + + configPathAbs, err := filepath.Abs(s.configPath) + if err != nil { + log.Fatal("[Daisy] Failed to get absolute config path") + } + wd := filepath.Dir(configPathAbs) + normalLoad(config, wd) + return subcommands.ExitSuccess +} + +func normalLoad(startUp daisy.Conf, wd string) { + srv := daisy.NewHttpServer(startUp, wd) + log.Printf("[Daisy] Starting HTTP server on '%s'\n", srv.Addr) + go utils.RunBackgroundHttp("HTTP", srv) + + exit_reload.ExitReload("Daisy", func() {}, func() { + // stop http server + _ = srv.Close() + }) +} diff --git a/go.mod b/go.mod index 59d3a51..59bc3ac 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,16 @@ module github.com/1f349/daisy go 1.22 + +require ( + github.com/1f349/violet v0.0.13 + github.com/emersion/go-webdav v0.5.0 + github.com/google/subcommands v1.2.0 + github.com/julienschmidt/httprouter v1.3.0 + github.com/mrmelon54/exit-reload v0.0.2 +) + +require ( + github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9 // indirect + golang.org/x/net v0.25.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..08eb2e0 --- /dev/null +++ b/go.sum @@ -0,0 +1,27 @@ +github.com/1f349/violet v0.0.13 h1:lJpTz15Ea83Uc1VAISXTjtKuzr8Pe8NM4cMGp3Aiyhk= +github.com/1f349/violet v0.0.13/go.mod h1:Ga5/hWqI+EkR6J1mAMNzs7aJhuGcA89XFqgQaDXC7Jo= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f/go.mod h1:2MKFUgfNMULRxqZkadG1Vh44we3y5gJAtTBlVsx1BKQ= +github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9 h1:ATgqloALX6cHCranzkLb8/zjivwQ9DWWDCQRnxTPfaA= +github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM= +github.com/emersion/go-webdav v0.5.0 h1:Ak/BQLgAihJt/UxJbCsEXDPxS5Uw4nZzgIMOq3rkKjc= +github.com/emersion/go-webdav v0.5.0/go.mod h1:ycyIzTelG5pHln4t+Y32/zBvmrM7+mV7x+V+Gx4ZQno= +github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/mrmelon54/exit-reload v0.0.2 h1:vqgfrMD/bF21HkDsWgg5+NLjFDrD3KGVEN/iTrMn9Ms= +github.com/mrmelon54/exit-reload v0.0.2/go.mod h1:aE3NhsqGMLUqmv6cJZRouC/8gXkZTvVSabRGOpI+Vjc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/teambition/rrule-go v1.7.2/go.mod h1:mBJ1Ht5uboJ6jexKdNUJg2NcwP8uUMNvStWXlJD3MvU= +github.com/teambition/rrule-go v1.8.2/go.mod h1:Ieq5AbrKGciP1V//Wq8ktsTXwSwJHDD5mD/wLBGl3p4= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server.go b/server.go new file mode 100644 index 0000000..86997f7 --- /dev/null +++ b/server.go @@ -0,0 +1,27 @@ +package daisy + +import ( + "github.com/emersion/go-webdav/carddav" + "net/http" + "time" +) + +type Conf struct { + Listen string `json:"listen"` +} + +func NewHttpServer(conf Conf, wd string) *http.Server { + h := &carddav.Handler{ + Backend: &Backend{}, + } + + return &http.Server{ + Addr: conf.Listen, + Handler: h, + ReadTimeout: time.Minute, + ReadHeaderTimeout: time.Minute, + WriteTimeout: time.Minute, + IdleTimeout: time.Minute, + MaxHeaderBytes: 2500, + } +}