aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-14 09:38:31 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-14 09:38:31 -0800
commit23947045c011e84149bc1b9d48805e57bb0bb3ba (patch)
treea4eb5015a5456a0ac93a792f59270675beccabd5 /web
parent22eacbaf2712aee2a1c448a0e53f241f8c7bd255 (diff)
downloadneko-23947045c011e84149bc1b9d48805e57bb0bb3ba.tar.gz
neko-23947045c011e84149bc1b9d48805e57bb0bb3ba.tar.bz2
neko-23947045c011e84149bc1b9d48805e57bb0bb3ba.zip
routing: make new UI default at / and move legacy UI to /v1/ (fixing NK-mgmn5m, NK-p89hyt)
Diffstat (limited to 'web')
-rw-r--r--web/routing_test.go75
-rw-r--r--web/web.go8
2 files changed, 82 insertions, 1 deletions
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: "<!doctype html>", // from React dist/v2
+ },
+ {
+ name: "/v2/ serves new UI",
+ path: "/v2/",
+ method: "GET",
+ expectedStatus: http.StatusOK,
+ containsBody: "<!doctype html>",
+ },
+ {
+ 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: "<title>neko rss mode</title>", // 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))
}