package server
import (
"fmt"
"io/fs"
"net/http"
"assistant/config"
)
// Run listens until the server stops (blocking).
func Run(cfg *config.ServerConfig, api *API) error {
mux := http.NewServeMux()
sub, err := fs.Sub(staticRoot, "static")
if err != nil {
return fmt.Errorf("static assets: %w", err)
}
mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.FS(sub))))
mux.HandleFunc("/api/status", api.handleStatus)
mux.HandleFunc("/ask/stream", api.handleAskStream)
mux.HandleFunc("/ask", api.handleAsk)
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
if path == "/" || path == "/index.html" {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
serveStaticHTML(w, "static/index.html")
return
}
api.handleNotFound(w, r)
})
addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
srv := &http.Server{
Addr: addr,
Handler: mux,
}
return srv.ListenAndServe()
}
func serveStaticHTML(w http.ResponseWriter, name string) {
b, err := staticRoot.ReadFile(name)
if err != nil {
http.Error(w, "not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
_, _ = w.Write(b)
}