From 23947045c011e84149bc1b9d48805e57bb0bb3ba Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Sat, 14 Feb 2026 09:38:31 -0800 Subject: routing: make new UI default at / and move legacy UI to /v1/ (fixing NK-mgmn5m, NK-p89hyt) --- web/routing_test.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ web/web.go | 8 +++++- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 web/routing_test.go (limited to 'web') diff --git a/web/routing_test.go b/web/routing_test.go new file mode 100644 index 0000000..972b208 --- /dev/null +++ b/web/routing_test.go @@ -0,0 +1,75 @@ +package web + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "adammathes.com/neko/config" +) + +func TestRouting(t *testing.T) { + config.Config.DigestPassword = "secret" + router := NewRouter(&config.Config) + + tests := []struct { + name string + path string + method string + cookie *http.Cookie + expectedStatus int + containsBody string + }{ + { + name: "Root serves new UI", + path: "/", + method: "GET", + expectedStatus: http.StatusOK, + containsBody: "", // from React dist/v2 + }, + { + name: "/v2/ serves new UI", + path: "/v2/", + method: "GET", + expectedStatus: http.StatusOK, + containsBody: "", + }, + { + name: "/v1/ redirects unauthenticated", + path: "/v1/", + method: "GET", + expectedStatus: http.StatusTemporaryRedirect, + }, + { + name: "/v1/ serves legacy UI when authenticated", + path: "/v1/", + method: "GET", + cookie: authCookie(), + expectedStatus: http.StatusOK, + containsBody: "neko rss mode", // from legacy ui.html + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := httptest.NewRequest(tt.method, tt.path, nil) + if tt.cookie != nil { + req.AddCookie(tt.cookie) + } + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + if rr.Code != tt.expectedStatus { + t.Errorf("Expected status %d, got %d", tt.expectedStatus, rr.Code) + } + + if tt.containsBody != "" { + body := strings.ToLower(rr.Body.String()) + if !strings.Contains(body, strings.ToLower(tt.containsBody)) { + t.Errorf("Expected body to contain %q, but it didn't", tt.containsBody) + } + } + }) + } +} diff --git a/web/web.go b/web/web.go index 11a5831..6c8e632 100644 --- a/web/web.go +++ b/web/web.go @@ -223,8 +223,14 @@ func NewRouter(cfg *config.Settings) http.Handler { mux.Handle("/static/", GzipMiddleware(http.StripPrefix("/static/", http.FileServer(http.FS(staticSub))))) // New Frontend (React/Vite) from web/dist/v2 + // Default route + mux.Handle("/", GzipMiddleware(http.HandlerFunc(ServeFrontend))) + // Also keep /v2/ for explicit access mux.Handle("/v2/", GzipMiddleware(http.StripPrefix("/v2/", http.HandlerFunc(ServeFrontend)))) + // Legacy UI at /v1/ + mux.Handle("/v1/", GzipMiddleware(http.StripPrefix("/v1/", AuthWrap(http.HandlerFunc(indexHandler))))) + // New REST API apiServer := api.NewServer(cfg) // We need to mount the raw mux from apiServer if we want /api/ access, @@ -257,7 +263,7 @@ func NewRouter(cfg *config.Settings) http.Handler { mux.HandleFunc("/api/logout", apiLogoutHandler) mux.HandleFunc("/api/auth", apiAuthStatusHandler) - mux.Handle("/", GzipMiddleware(AuthWrap(http.HandlerFunc(indexHandler)))) + // Removed default root handler for legacy UI return SecurityHeadersMiddleware(CSRFMiddleware(mux)) } -- cgit v1.2.3