package graph import ( "io" "net/http" "os" "strings" "github.com/brasse-b/archivum/internal/config" ) func NewServer(cfg *config.Config) http.Handler { mux := http.NewServeMux() mux.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) return } if cfg == nil { _, _ = w.Write([]byte(`{"data":{"systemStatus":"REQUIRE_SETUP"}}`)) return } // Stub: inspect operation name to return sensible responses. body, _ := io.ReadAll(r.Body) bs := string(body) switch { case strings.Contains(bs, "testLdapConnection"): _, _ = w.Write([]byte(`{"data":{"testLdapConnection":{"success":false,"message":"LDAP resolver not yet implemented"}}}`)) case strings.Contains(bs, "setup"): _, _ = w.Write([]byte(`{"data":{"setup":true}}`)) case strings.Contains(bs, "login"): _, _ = w.Write([]byte(`{"data":{"login":"stub-token"}}`)) default: _, _ = w.Write([]byte(`{"data":{"systemStatus":"OK","documents":[]}}`)) } }) mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) uiDir := os.Getenv("UI_DIR") if uiDir == "" { uiDir = "/srv/archivum/ui" } mux.Handle("/", spaHandler(uiDir)) return mux } // spaHandler serves static files and falls back to index.html for all paths // that don't resolve to a real file — required for client-side routing. func spaHandler(dir string) http.Handler { fs := http.Dir(dir) fileServer := http.FileServer(fs) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Assets (JS, CSS, images) must be served as-is. if isAssetPath(r.URL.Path) { fileServer.ServeHTTP(w, r) return } // Try to open the path; if it exists serve it, otherwise serve SPA root. f, err := fs.Open(r.URL.Path) if err == nil { f.Close() fileServer.ServeHTTP(w, r) return } http.ServeFile(w, r, dir+"/index.html") }) } func isAssetPath(path string) bool { return strings.HasPrefix(path, "/assets/") || strings.HasPrefix(path, "/icons/") || path == "/favicon.ico" || path == "/favicon.svg" || path == "/manifest.webmanifest" || path == "/registerSW.js" || path == "/sw.js" }