package websocket import ( "context" "net/http" ws "github.com/coder/websocket" "git.avsdev.uk/Go/job-search/internal/middleware" ) // ServeHTTP upgrades an http connection and runs the client until it closes. // A browser's upgrade must come from the server's own origin or a trusted one // (see WithTrustedOrigins); a request without an Origin header, which only a // non-browser client sends, is accepted. func (h *Hub) ServeHTTP(w http.ResponseWriter, r *http.Request) { mode := ws.CompressionDisabled if h.conf.EnableCompression { mode = ws.CompressionContextTakeover } // Accept enforces the Origin check: same host, or one of OriginPatterns. // That is the defence against cross-site WebSocket hijacking. A pattern // holding "://" is matched against the origin's scheme and host. conn, err := ws.Accept(w, r, &ws.AcceptOptions{ CompressionMode: mode, OriginPatterns: h.trustedOrigins, }) if err != nil { h.logger().Debug("upgrade failed", "error", err) return // Accept has already written the HTTP error. } defer conn.CloseNow() //nolint:errcheck // finished with; it may already be closed conn.SetReadLimit(int64(h.maxMessageSize())) ip := middleware.ClientIP(r) ctx, cancel := context.WithCancel(r.Context()) client := newClient(h, conn, ip, cancel) if !h.register(client) { cancel() conn.Close(ws.StatusGoingAway, "server shutting down") //nolint:errcheck,gosec // turned away return } defer h.unregister(client) h.logger().Info("client connected", "client", client.id, "ip", ip) client.run(ctx) h.logger().Info("client disconnected", "client", client.id, "ip", ip) }