package webui import ( "net/http" "os" "path/filepath" "strings" "github.com/go-chi/chi/v5" "ds2api/internal/config" ) const welcomeHTML = ` DS2API

DS2API

DeepSeek to OpenAI & Claude Compatible API

` type Handler struct { StaticDir string } func NewHandler() *Handler { return &Handler{StaticDir: config.StaticAdminDir()} } func RegisterRoutes(r chi.Router, h *Handler) { r.Get("/", h.index) r.Get("/admin", h.admin) } func (h *Handler) HandleAdminFallback(w http.ResponseWriter, r *http.Request) bool { if r.Method != http.MethodGet { return false } if !strings.HasPrefix(r.URL.Path, "/admin/") { return false } h.admin(w, r) return true } func (h *Handler) index(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(welcomeHTML)) } func (h *Handler) admin(w http.ResponseWriter, r *http.Request) { if fi, err := os.Stat(h.StaticDir); err != nil || !fi.IsDir() { http.Error(w, "WebUI not built. Run `cd webui && npm run build` first.", http.StatusNotFound) return } path := strings.TrimPrefix(r.URL.Path, "/admin") path = strings.TrimPrefix(path, "/") if path != "" && strings.Contains(path, ".") { full := filepath.Join(h.StaticDir, filepath.Clean(path)) if !strings.HasPrefix(full, h.StaticDir) { http.NotFound(w, r) return } if _, err := os.Stat(full); err == nil { if strings.HasPrefix(path, "assets/") { w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") } else { w.Header().Set("Cache-Control", "no-store, must-revalidate") } http.ServeFile(w, r, full) return } http.NotFound(w, r) return } index := filepath.Join(h.StaticDir, "index.html") if _, err := os.Stat(index); err != nil { http.Error(w, "index.html not found", http.StatusNotFound) return } w.Header().Set("Cache-Control", "no-store, must-revalidate") http.ServeFile(w, r, index) }