feat(api): wire voteLtr rate limiter for upvote endpoint (§13.6)

Add dedicated 10/hour-per-IP rate limiter for POST /api/feedback/{id}/upvote,
separate from the 20/hour feedback submission limiter. Wired in main.go init,
server_test.go helper, and RegisterRoutes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-04-22 17:37:34 -04:00
parent 477a54c548
commit 7df2fad568
3 changed files with 8 additions and 1 deletions

View file

@ -84,6 +84,7 @@ func main() {
feedbackLtr: ratelimit.NewLimiter(20, 20.0/3600), // 20/hour per IP
predictLtr: ratelimit.NewLimiter(60, 60.0/3600), // 60/hour per IP
submitLtr: ratelimit.NewLimiter(5, 5.0/86400), // 5/day per key
voteLtr: ratelimit.NewLimiter(10, 10.0/3600), // 10/hour per IP
}
// Periodically purge stale rate-limit buckets (every 10 min)
@ -95,6 +96,7 @@ func main() {
srv.feedbackLtr.Cleanup(time.Hour)
srv.predictLtr.Cleanup(time.Hour)
srv.submitLtr.Cleanup(24 * time.Hour)
srv.voteLtr.Cleanup(time.Hour)
}
}()

View file

@ -30,6 +30,7 @@ type Server struct {
feedbackLtr *ratelimit.Limiter // 20/hour per IP
predictLtr *ratelimit.Limiter // 60/hour per IP
submitLtr *ratelimit.Limiter // 5/day per bot_id
voteLtr *ratelimit.Limiter // 10/hour per IP
}
func (s *Server) RegisterRoutes(mux *http.ServeMux) {
@ -69,9 +70,12 @@ func (s *Server) RegisterRoutes(mux *http.ServeMux) {
fbMW := s.feedbackLtr.Middleware(ipKey, func() {
metrics.RateLimitHits.WithLabelValues("feedback").Inc()
})
voteMW := s.voteLtr.Middleware(ipKey, func() {
metrics.RateLimitHits.WithLabelValues("vote").Inc()
})
mux.HandleFunc("POST /api/feedback", fbMW(http.HandlerFunc(s.handleUIFeedback)).ServeHTTP)
mux.HandleFunc("GET /api/feedback/", s.handleGetFeedback)
mux.HandleFunc("POST /api/feedback/", fbMW(http.HandlerFunc(s.handleFeedbackUpvote)).ServeHTTP)
mux.HandleFunc("POST /api/feedback/", voteMW(http.HandlerFunc(s.handleFeedbackUpvote)).ServeHTTP)
// Predictions — 60/hour per IP
predMW := s.predictLtr.Middleware(ipKey, func() {

View file

@ -22,6 +22,7 @@ func newTestServer() *Server {
feedbackLtr: ratelimit.NewLimiter(20, 20.0/3600),
predictLtr: ratelimit.NewLimiter(60, 60.0/3600),
submitLtr: ratelimit.NewLimiter(5, 5.0/86400),
voteLtr: ratelimit.NewLimiter(10, 10.0/3600),
}
}