Log push send response bodies (diagnose Apple 403) + no-cache static assets
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 files changed,
+20
−6
main.go+10 −1push.go+10 −5
diff --git a/main.go b/main.go| index bdb729f..22f9ef7 100644 |
| --- a/main.go |
| +++ b/main.go |
| @@ -86,7 +86,7 @@ func (s *Server) handler() http.Handler { |
| mux.HandleFunc("GET /", s.servePage("index.html")) |
| mux.HandleFunc("GET /admin", s.servePage("admin.html")) |
| mux.HandleFunc("GET /join/{token}", s.servePage("join.html")) |
| - mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS)))) |
| + mux.Handle("GET /static/", noCache(http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))) |
| // Chat API (transport auth via invite token; never sees plaintext) |
| mux.HandleFunc("GET /api/messages", s.getMessages) |
| @@ -374,6 +374,15 @@ func (s *Server) setGroup(w http.ResponseWriter, r *http.Request) { |
| // ---- helpers ------------------------------------------------------------ |
| +// noCache makes browsers revalidate static assets, so deploys take effect without |
| +// a hard reload. |
| +func noCache(h http.Handler) http.Handler { |
| + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| + w.Header().Set("Cache-Control", "no-cache") |
| + h.ServeHTTP(w, r) |
| + }) |
| +} |
| + |
| func writeJSON(w http.ResponseWriter, status int, v any) { |
| w.Header().Set("Content-Type", "application/json") |
| w.WriteHeader(status) |
diff --git a/push.go b/push.go| index de6a5a9..6f21e8f 100644 |
| --- a/push.go |
| +++ b/push.go |
| @@ -2,6 +2,7 @@ package main |
| import ( |
| "encoding/json" |
| + "io" |
| "log" |
| "net/http" |
| "time" |
| @@ -118,13 +119,17 @@ func (s *Server) sendToAll(payload []byte, kind string) int { |
| log.Printf("push[%s]: send error: %v", kind, err) |
| continue |
| } |
| - log.Printf("push[%s]: status %d (%.45s…)", kind, resp.StatusCode, sub.Endpoint) |
| + if resp.StatusCode >= 200 && resp.StatusCode < 300 { |
| + sent++ |
| + resp.Body.Close() |
| + log.Printf("push[%s]: status %d (%.45s…)", kind, resp.StatusCode, sub.Endpoint) |
| + continue |
| + } |
| + body, _ := io.ReadAll(io.LimitReader(resp.Body, 400)) |
| resp.Body.Close() |
| - switch { |
| - case resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusGone: |
| + log.Printf("push[%s]: status %d body=%q (%.45s…)", kind, resp.StatusCode, string(body), sub.Endpoint) |
| + if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusGone { |
| _ = s.db.deleteSubscription(sub.Endpoint) |
| - case resp.StatusCode >= 200 && resp.StatusCode < 300: |
| - sent++ |
| } |
| } |
| return sent |