96 lines
2.8 KiB
Go
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)
|
|
}
|