aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-16 10:51:05 -0800
committerGitHub <noreply@github.com>2026-02-16 10:51:05 -0800
commitc5fdd406503aaedaac5e117e710d7910112af83f (patch)
tree3a8b7b1d9277ba0db4c946fea43043d65220fd8d /web
parent8b852475d7952f37b630480af76897baca06e937 (diff)
parentd4caf45b2b9ea6a3276de792cf6f73085e66b1ae (diff)
downloadneko-c5fdd406503aaedaac5e117e710d7910112af83f.tar.gz
neko-c5fdd406503aaedaac5e117e710d7910112af83f.tar.bz2
neko-c5fdd406503aaedaac5e117e710d7910112af83f.zip
Merge pull request #4 from adammathes/claude/performance-stress-testing-qQuV8
Add performance benchmarks, stress tests, and frontend perf tests
Diffstat (limited to 'web')
-rw-r--r--web/web_bench_test.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/web/web_bench_test.go b/web/web_bench_test.go
new file mode 100644
index 0000000..7897fc7
--- /dev/null
+++ b/web/web_bench_test.go
@@ -0,0 +1,92 @@
+package web
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ "adammathes.com/neko/config"
+)
+
+func BenchmarkGzipMiddleware(b *testing.B) {
+ // Simulate a JSON API response
+ jsonPayload := `[` + strings.Repeat(`{"_id":"1","title":"Test Item","url":"https://example.com","description":"<p>This is a test description with enough content to be worth compressing in a real scenario</p>","read":false,"starred":false},`, 14) +
+ `{"_id":"15","title":"Last Item","url":"https://example.com/15","description":"<p>Final item</p>","read":false,"starred":false}]`
+
+ handler := GzipMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(jsonPayload))
+ }))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ req := httptest.NewRequest("GET", "/api/stream", nil)
+ req.Header.Set("Accept-Encoding", "gzip")
+ rr := httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ }
+}
+
+func BenchmarkSecurityHeaders(b *testing.B) {
+ handler := SecurityHeadersMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ }))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ req := httptest.NewRequest("GET", "/", nil)
+ rr := httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ }
+}
+
+func BenchmarkCSRFMiddleware(b *testing.B) {
+ cfg := &config.Settings{SecureCookies: false}
+ handler := CSRFMiddleware(cfg, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ }))
+
+ // Pre-generate a CSRF token by doing an initial GET
+ initReq := httptest.NewRequest("GET", "/", nil)
+ initRR := httptest.NewRecorder()
+ handler.ServeHTTP(initRR, initReq)
+
+ var csrfCookie *http.Cookie
+ for _, c := range initRR.Result().Cookies() {
+ if c.Name == "csrf_token" {
+ csrfCookie = c
+ break
+ }
+ }
+ if csrfCookie == nil {
+ b.Fatal("no csrf cookie set")
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ req := httptest.NewRequest("POST", "/api/stream", nil)
+ req.AddCookie(csrfCookie)
+ req.Header.Set("X-CSRF-Token", csrfCookie.Value)
+ rr := httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ }
+}
+
+func BenchmarkFullMiddlewareStack(b *testing.B) {
+ cfg := &config.Settings{SecureCookies: false}
+ inner := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"status":"ok"}`))
+ })
+
+ handler := SecurityHeadersMiddleware(CSRFMiddleware(cfg, GzipMiddleware(inner)))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ req := httptest.NewRequest("GET", "/", nil)
+ req.Header.Set("Accept-Encoding", "gzip")
+ rr := httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ }
+}