Skip to content

Commit 4d8c831

Browse files
authored
Merge pull request #34 from tstromberg/main
Fix shutdown panic
2 parents 05bb80a + 9ddf2fa commit 4d8c831

File tree

9 files changed

+1258
-208
lines changed

9 files changed

+1258
-208
lines changed

cmd/server/main.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ var (
4646
leEmail = flag.String("le-email", "", "Contact email for Let's Encrypt notifications")
4747
maxConnsPerIP = flag.Int("max-conns-per-ip", 10, "Maximum WebSocket connections per IP")
4848
maxConnsTotal = flag.Int("max-conns-total", 1000, "Maximum total WebSocket connections")
49-
rateLimit = flag.Int("rate-limit", 100, "Maximum requests per minute per IP")
5049
allowedEvents = flag.String("allowed-events", func() string {
5150
if value := os.Getenv("ALLOWED_WEBHOOK_EVENTS"); value != "" {
5251
return value
@@ -92,8 +91,7 @@ func main() {
9291
hub := srv.NewHub()
9392
go hub.Run(ctx)
9493

95-
// Create security components
96-
rateLimiter := security.NewRateLimiter(*rateLimit)
94+
// Create connection limiter for WebSocket connections
9795
connLimiter := security.NewConnectionLimiter(*maxConnsPerIP, *maxConnsTotal)
9896

9997
mux := http.NewServeMux()
@@ -133,16 +131,6 @@ func main() {
133131
return
134132
}
135133

136-
// Rate limiting
137-
if !rateLimiter.Allow(ip) {
138-
log.Printf("Webhook 429: rate limit exceeded ip=%s", ip)
139-
w.WriteHeader(http.StatusTooManyRequests)
140-
if _, err := w.Write([]byte("429 Too Many Requests: Rate limit exceeded\n")); err != nil {
141-
log.Printf("failed to write 429 response: %v", err)
142-
}
143-
return
144-
}
145-
146134
webhookHandler.ServeHTTP(w, r)
147135
log.Printf("Webhook complete: ip=%s duration=%v", ip, time.Since(startTime))
148136
})
@@ -185,16 +173,6 @@ func main() {
185173
return
186174
}
187175

188-
// Rate limiting check
189-
if !rateLimiter.Allow(ip) {
190-
log.Printf("WebSocket 429: rate limit exceeded ip=%s", ip)
191-
w.WriteHeader(http.StatusTooManyRequests)
192-
if _, err := w.Write([]byte("429 Too Many Requests: Rate limit exceeded\n")); err != nil {
193-
log.Printf("failed to write 429 response: %v", err)
194-
}
195-
return
196-
}
197-
198176
// Pre-validate authentication before WebSocket upgrade
199177
authHeader := r.Header.Get("Authorization")
200178
if !wsHandler.PreValidateAuth(r) {
@@ -287,9 +265,6 @@ func main() {
287265
// Stop accepting new connections
288266
hub.Stop()
289267

290-
// Stop the rate limiter cleanup routine
291-
rateLimiter.Stop()
292-
293268
// Stop the connection limiter cleanup routine
294269
connLimiter.Stop()
295270

pkg/client/client.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,14 +468,25 @@ func (c *Client) connect(ctx context.Context) error {
468468
// Start ping sender (sends to write channel, not directly to websocket)
469469
pingCtx, cancelPing := context.WithCancel(ctx)
470470
defer cancelPing()
471-
go c.sendPings(pingCtx)
471+
pingDone := make(chan struct{})
472+
go func() {
473+
c.sendPings(pingCtx)
474+
close(pingDone)
475+
}()
472476

473477
// Read events - when this returns, cancel everything
474478
readErr := c.readEvents(ctx, ws)
475479

476-
// Stop write pump and ping sender
477-
cancelWrite()
480+
// Stop ping sender first - this ensures no more writes will be queued
478481
cancelPing()
482+
<-pingDone // Wait for ping sender to fully exit
483+
484+
// Stop write pump
485+
cancelWrite()
486+
487+
// Close write channel to signal writePump to exit cleanly
488+
// Safe to close now because ping sender has exited and won't write anymore
489+
close(c.writeCh)
479490

480491
// Wait for write pump to finish
481492
writeErr := <-writeDone

0 commit comments

Comments
 (0)