internal/server/server.go (view raw)
1package server
2
3import (
4 "context"
5 "io/fs"
6 "net/http"
7
8 "github.com/mjensen/weimar/internal/config"
9)
10
11func New(cfg config.Config, webFS fs.FS) (*Server, error) {
12 mux := http.NewServeMux()
13
14 // API routes
15 mux.HandleFunc("GET /api/health", handleHealth)
16
17 // Auth
18 mux.HandleFunc("POST /api/auth/login", handleNotImplemented)
19 mux.HandleFunc("POST /api/auth/register", handleNotImplemented)
20
21 // Images
22 mux.HandleFunc("POST /api/upload", handleNotImplemented)
23 mux.HandleFunc("GET /api/images", handleNotImplemented)
24 mux.HandleFunc("GET /api/images/{id}", handleNotImplemented)
25 mux.HandleFunc("GET /api/images/{id}/download", handleNotImplemented)
26 mux.HandleFunc("GET /api/images/{id}/thumbnail", handleNotImplemented)
27
28 // Tags
29 mux.HandleFunc("GET /api/tags/suggest", handleNotImplemented)
30
31 // SPA — serve index.html for all non-API, non-file routes
32 spaFS := http.FileServer(http.FS(webFS))
33 mux.Handle("/", spaFS)
34
35 return &Server{
36 cfg: cfg,
37 mux: mux,
38 }, nil
39}
40
41type Server struct {
42 cfg config.Config
43 mux *http.ServeMux
44}
45
46func (s *Server) Start(ctx context.Context) error {
47 addr := s.cfg.Server.Host + ":" + itoa(s.cfg.Server.Port)
48 srv := &http.Server{Addr: addr, Handler: s.mux}
49
50 go func() {
51 <-ctx.Done()
52 srv.Shutdown(context.Background())
53 }()
54
55 return srv.ListenAndServe()
56}
57
58func itoa(n int) string {
59 if n == 0 {
60 return "0"
61 }
62 var buf [20]byte
63 i := len(buf)
64 for n > 0 {
65 i--
66 buf[i] = byte('0' + n%10)
67 n /= 10
68 }
69 return string(buf[i:])
70}
71
72func handleHealth(w http.ResponseWriter, r *http.Request) {
73 w.Header().Set("Content-Type", "application/json")
74 w.Write([]byte(`{"status":"ok"}`))
75}
76
77func handleNotImplemented(w http.ResponseWriter, r *http.Request) {
78 http.Error(w, "not implemented", http.StatusNotImplemented)
79}