refactor(websocket): split controller into service + thin controller

Move per-connection lifecycle out of the controller and into a new
service.WebSocketService. The controller is now HTTP-layer only:
authenticate, validate origin, upgrade, and hand the connection off.

- web/service/websocket.go (new): owns the read/write pumps, hub
  registration, and connection lifetime. Pump constants are prefixed
  (wsWriteWait, wsPongWait, wsPingPeriod, wsClientReadLimit) to avoid
  collisions in the larger service package namespace.
- web/controller/websocket.go: trimmed to the upgrader, same-origin
  check, auth gate, and hand-off to the service.
- web/web.go: wires controller.NewWebSocketController(service.NewWebSocketService(hub)).

The hub package (web/websocket) stays as low-level fan-out
infrastructure. Behavior is unchanged — this is a structural cleanup
to align with the rest of the codebase's controller/service split.

Also includes a small range-int modernization in login_limiter_test.go
that gopls flagged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
MHSanaei
2026-05-08 00:00:44 +02:00
parent b84b58ef21
commit c394938f01
4 changed files with 133 additions and 90 deletions
+3 -2
View File
@@ -289,8 +289,9 @@ func (s *Server) initRouter() (*gin.Engine, error) {
s.wsHub = websocket.NewHub()
go s.wsHub.Run()
// Initialize WebSocket controller
s.ws = controller.NewWebSocketController(s.wsHub)
// Initialize WebSocket controller — service owns per-connection pumps,
// controller is HTTP-layer only (auth + upgrade).
s.ws = controller.NewWebSocketController(service.NewWebSocketService(s.wsHub))
// Register WebSocket route with basePath (g already has basePath prefix)
g.GET("/ws", s.ws.HandleWebSocket)