Files
aethera/backend/internal/server/server.go
2026-01-17 10:07:21 -05:00

96 lines
2.8 KiB
Go

package server
import (
"fmt"
"net/http"
"path"
"time"
"github.com/sirupsen/logrus"
"reichard.io/aethera/internal/api"
"reichard.io/aethera/internal/store"
)
func StartServer(settingsStore store.Store, dataDir, listenAddress string, listenPort int) {
mux := http.NewServeMux()
// Create API Instance - use settingsStore as the unified store for both settings and chat
logger := logrus.New()
api := api.New(settingsStore, dataDir, logger)
feFS := http.FileServer(http.Dir("../frontend/public/"))
mux.Handle("GET /", feFS)
// Serve UI Pages
pagesFS := http.FileServer(http.Dir("../frontend/public/pages/"))
mux.Handle("GET /pages/", http.StripPrefix("/pages/", pagesFS))
// Serve Generated Data
genFS := http.FileServer(http.Dir(path.Join(dataDir, "generated")))
mux.Handle("GET /generated/", http.StripPrefix("/generated/", genFS))
// Register API Routes
mux.HandleFunc("POST /api/images", api.PostImage)
mux.HandleFunc("GET /api/settings", api.GetSettings)
mux.HandleFunc("POST /api/settings", api.PostSettings)
mux.HandleFunc("GET /api/models", api.GetModels)
mux.HandleFunc("GET /api/images", api.GetImages)
mux.HandleFunc("DELETE /api/images/{filename}", api.DeleteImage)
// Register Chat Management Routes
mux.HandleFunc("GET /api/chats", api.GetChats)
mux.HandleFunc("POST /api/chats", api.PostChat)
mux.HandleFunc("GET /api/chats/{chatId}", api.GetChat)
mux.HandleFunc("POST /api/chats/{chatId}", api.PostChatMessage)
mux.HandleFunc("DELETE /api/chats/{chatId}", api.DeleteChat)
// Wrap Logging
wrappedMux := loggingMiddleware(mux)
logrus.Infof("Starting server on %s:%d with data directory: %s", listenAddress, listenPort, dataDir)
logrus.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", listenAddress, listenPort), wrappedMux))
}
// loggingMiddleware wraps an http.Handler and logs requests
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
ww := &responseWriterWrapper{ResponseWriter: w}
next.ServeHTTP(ww, r)
logrus.WithFields(logrus.Fields{
"datetime": start.UTC().Format(time.RFC3339),
"method": r.Method,
"path": r.URL.Path,
"remote": r.RemoteAddr,
"status": ww.getStatusCode(),
"latency": time.Since(start),
}).Infof("%s %s", r.Method, r.URL.Path)
})
}
// responseWriterWrapper wraps http.ResponseWriter to capture status code
type responseWriterWrapper struct {
http.ResponseWriter
statusCode int
}
func (w *responseWriterWrapper) Flush() {
if f, ok := w.ResponseWriter.(http.Flusher); ok {
f.Flush()
}
}
func (rw *responseWriterWrapper) getStatusCode() int {
if rw.statusCode == 0 {
return 200
}
return rw.statusCode
}
func (rw *responseWriterWrapper) WriteHeader(code int) {
if code > 0 {
rw.statusCode = code
}
rw.ResponseWriter.WriteHeader(code)
}