103 lines
2.5 KiB
Go
103 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
originclient "git.warky.dev/wdevs/origin_client/go"
|
|
"wedding-server/internal/api"
|
|
"wedding-server/internal/config"
|
|
"wedding-server/internal/mail"
|
|
"wedding-server/internal/store"
|
|
"wedding-server/internal/webhook"
|
|
)
|
|
|
|
//go:embed all:web/dist
|
|
var embeddedWeb embed.FS
|
|
|
|
func main() {
|
|
cfgPath := config.Path()
|
|
cfg, err := config.Load(cfgPath)
|
|
if err != nil {
|
|
log.Fatalf("config: %v", err)
|
|
}
|
|
|
|
if err := os.MkdirAll(cfg.Storage.DataDir, 0o755); err != nil {
|
|
log.Fatalf("data dir: %v", err)
|
|
}
|
|
|
|
st, err := store.Open(cfg.Storage.DataDir)
|
|
if err != nil {
|
|
log.Fatalf("store: %v", err)
|
|
}
|
|
defer st.Close()
|
|
|
|
mailer := mail.New(cfg.Email)
|
|
wh := webhook.New(cfg.Webhook)
|
|
if cfg.Origin.ServiceKey == "" {
|
|
log.Printf("origin registration disabled: origin.service_key is not configured")
|
|
} else {
|
|
origin, err := originclient.New(originclient.Config{
|
|
URL: cfg.Origin.URL,
|
|
ServiceKey: cfg.Origin.ServiceKey,
|
|
Type: "generic",
|
|
Version: cfg.Origin.Version,
|
|
Name: "ZoeShaldon",
|
|
AppType: "go",
|
|
Port: cfg.Server.Port,
|
|
BaseURL: cfg.Site.URL,
|
|
Description: "CronoCraft App - ZoeShaldon wedding site",
|
|
})
|
|
if err != nil {
|
|
log.Fatalf("origin client: %v", err)
|
|
}
|
|
go origin.Run(context.Background())
|
|
}
|
|
|
|
mux := http.NewServeMux()
|
|
api.New(cfg, st, mailer, wh).Routes(mux)
|
|
|
|
uploadsDir := filepath.Join(cfg.Storage.DataDir, "photos")
|
|
mux.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir(uploadsDir))))
|
|
|
|
webFS, err := fs.Sub(embeddedWeb, "web/dist")
|
|
if err != nil {
|
|
log.Fatalf("embedded web assets: %v", err)
|
|
}
|
|
mux.Handle("/", staticHandler(webFS))
|
|
|
|
addr := fmt.Sprintf(":%d", cfg.Server.Port)
|
|
log.Printf("listening on %s", addr)
|
|
if err := http.ListenAndServe(addr, mux); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// staticHandler serves the prerendered SvelteKit build, where routes are
|
|
// written as flat files (e.g. "rsvp.html") rather than "rsvp/index.html".
|
|
func staticHandler(fsys fs.FS) http.Handler {
|
|
fileServer := http.FileServer(http.FS(fsys))
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
p := strings.TrimPrefix(r.URL.Path, "/")
|
|
if p == "" {
|
|
p = "index.html"
|
|
}
|
|
if _, err := fs.Stat(fsys, p); err != nil {
|
|
if _, err := fs.Stat(fsys, p+".html"); err == nil {
|
|
r2 := *r
|
|
r2.URL.Path = "/" + p + ".html"
|
|
fileServer.ServeHTTP(w, &r2)
|
|
return
|
|
}
|
|
}
|
|
fileServer.ServeHTTP(w, r)
|
|
})
|
|
}
|