fix: enforce request body size limits across the API
Ultraworked with Sisyphus (https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -20,10 +20,11 @@ type SquareWebhookEvent struct {
|
||||
}
|
||||
|
||||
func HandleSquareWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 512*1024)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read webhook body: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
http.Error(w, "request body too large or unreadable", http.StatusRequestEntityTooLarge)
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
+23
-5
@@ -42,6 +42,22 @@ func init() {
|
||||
auth.InitJWT(jwtSecret)
|
||||
}
|
||||
|
||||
func limitBody(limit int64) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Body != nil {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, limit)
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
defaultBodyLimit int64 = 1 * 1024 * 1024 // 1MB
|
||||
uploadBodyLimit int64 = 15 * 1024 * 1024 // 15MB
|
||||
)
|
||||
|
||||
func initDB() {
|
||||
if err := db.Connect(); err != nil {
|
||||
log.Fatal("Failed to connect to DB:", err)
|
||||
@@ -146,11 +162,11 @@ func main() {
|
||||
r.With(mw.RateLimit(10, time.Minute)).Post("/register", authHandlers.RegisterHandler)
|
||||
|
||||
// Login: Has its own internal rate limiting
|
||||
r.Post("/login", authHandlers.LoginHandler)
|
||||
r.With(mw.RateLimit(10, time.Minute)).Post("/login", authHandlers.LoginHandler)
|
||||
|
||||
// Email verification
|
||||
r.Post("/verify/generate", authHandlers.GenerateVerificationCodeHandler)
|
||||
r.Post("/verify/check", authHandlers.VerifyCodeHandler)
|
||||
r.With(mw.RateLimit(10, time.Minute)).Post("/verify/generate", authHandlers.GenerateVerificationCodeHandler)
|
||||
r.With(mw.RateLimit(20, time.Minute)).Post("/verify/check", authHandlers.VerifyCodeHandler)
|
||||
|
||||
// Health check
|
||||
r.Get("/health", healthCheckHandler)
|
||||
@@ -169,7 +185,7 @@ func main() {
|
||||
r.Use(mw.RequireAuth)
|
||||
r.Use(mw.RequireAdmin)
|
||||
r.Use(mw.RateLimit(60, time.Minute))
|
||||
r.Post("/images", portfolio.UploadImage)
|
||||
r.With(limitBody(uploadBodyLimit)).Post("/images", portfolio.UploadImage)
|
||||
r.Delete("/images/{id}", portfolio.DeleteImage)
|
||||
})
|
||||
})
|
||||
@@ -208,12 +224,12 @@ func main() {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(mw.RequireAuth)
|
||||
r.Use(mw.RateLimit(120, time.Minute))
|
||||
r.Use(limitBody(defaultBodyLimit))
|
||||
|
||||
r.Post("/refresh-token", authHandlers.RefreshTokenHandler)
|
||||
|
||||
r.Get("/user/profile", user.GetProfileHandler)
|
||||
r.Put("/user/profile", user.UpdateProfileHandler)
|
||||
r.Post("/user/profile-picture", user.UploadProfilePictureHandler)
|
||||
r.Put("/user/change-password", user.ChangePasswordHandler)
|
||||
r.Get("/user/notification-preferences", user.GetNotificationPreferencesHandler)
|
||||
r.Put("/user/notification-preferences", user.UpdateNotificationPreferencesHandler)
|
||||
@@ -239,6 +255,8 @@ func main() {
|
||||
r.Get("/bookings/{id}/payment-summary", payments.GetBookingPaymentSummary)
|
||||
})
|
||||
|
||||
r.With(mw.RequireAuth, mw.RequireVerified, limitBody(uploadBodyLimit)).Post("/user/profile-picture", user.UploadProfilePictureHandler)
|
||||
|
||||
// Admin-only (no rate limit - trusted users with authenticated sessions)
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(mw.RequireAuth)
|
||||
|
||||
Reference in New Issue
Block a user