-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgomp.go
114 lines (96 loc) · 3.08 KB
/
gomp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"github.com/chadweimer/gomp/api"
"github.com/chadweimer/gomp/conf"
"github.com/chadweimer/gomp/db"
"github.com/chadweimer/gomp/metadata"
"github.com/chadweimer/gomp/middleware"
"github.com/chadweimer/gomp/upload"
)
func main() {
// Start with a logger that defaults to the info level, until we load configuration
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
})))
// Write the app metadata to logs
slog.Info("Starting application", "version", metadata.BuildVersion)
// Load configuration
cfg := &Config{}
if err := conf.Bind(cfg); err != nil {
slog.Error("Failed to load configuration. Exiting...", "error", err)
os.Exit(1)
}
// Reconfigure the logger now that we've loaded the main application configuation
if cfg.IsDevelopment {
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
})))
}
// Now it's OK to log what was loaded
slog.Debug("Loaded application configuration", "cfg", cfg)
if err := cfg.validate(); err != nil {
slog.Error("Invalid configuration. Exiting...", "error", err)
os.Exit(1)
}
uplDriver, err := upload.CreateDriver(cfg.Upload.Driver)
if err != nil {
slog.Error("Establishing upload driver failed. Exiting...", "error", err)
os.Exit(1)
}
uploader, err := upload.CreateImageUploader(uplDriver, cfg.Upload.Image)
if err != nil {
slog.Error("Establishing uploader failed. Exiting...", "error", err)
os.Exit(1)
}
dbDriver, err := db.CreateDriver(cfg.Database)
if err != nil {
slog.Error("Establishing database driver failed. Exiting...", "error", err)
os.Exit(1)
}
defer dbDriver.Close()
mux := http.NewServeMux()
mux.Handle("/api/*", http.StripPrefix("/api", api.NewHandler(cfg.SecureKeys, uploader, dbDriver)))
mux.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.FS(upload.OnlyFiles(os.DirFS(cfg.BaseAssetsPath))))))
mux.Handle("/uploads/*", http.StripPrefix("/uploads/", http.FileServer(http.FS(uplDriver))))
mux.Handle("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filepath.Join(cfg.BaseAssetsPath, "index.html"))
}))
r := middleware.Wrap(
mux,
middleware.LogRequests(slog.Default()),
middleware.Recover("Recovered from panic"),
)
// subscribe to SIGINT signals
stopChan := make(chan os.Signal, 1)
signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
timeout := 10 * time.Second
if cfg.IsDevelopment {
timeout = 1 * time.Second
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
slog.Info("Starting server", "port", cfg.Port)
srv := &http.Server{
ReadHeaderTimeout: 10 * time.Second,
Addr: fmt.Sprintf(":%d", cfg.Port),
Handler: r,
}
go srv.ListenAndServe()
// Wait for a stop signal
<-stopChan
slog.Info("Shutting down server...")
// Shutdown the http server
if err := srv.Shutdown(ctx); err != nil {
// We're already going down. Time to panic
panic(err)
}
}