From ae95a3fd20b5dc8c25ee947f5cc8e120a185b8bc Mon Sep 17 00:00:00 2001 From: bndw Date: Sun, 15 Feb 2026 10:06:26 -0800 Subject: fix: improve WebSocket error responses and protocol compliance - Send OK false for rate limit errors instead of NOTICE - Send OK false for auth errors (e.g. pubkey not in allowlist) - Remove OK response for AUTH events (AUTH is not an EVENT type) - Parse event before auth checks to get event ID for error responses These changes improve client UX by providing immediate, structured feedback for all rejection cases instead of generic NOTICE messages. The AUTH event OK removal fixes a bug where clients would read the wrong response when sending EVENT after AUTH. --- internal/handler/websocket/handler.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'internal/handler/websocket') diff --git a/internal/handler/websocket/handler.go b/internal/handler/websocket/handler.go index 5201698..a23dd60 100644 --- a/internal/handler/websocket/handler.go +++ b/internal/handler/websocket/handler.go @@ -257,18 +257,19 @@ func (h *Handler) handleEvent(ctx context.Context, conn *websocket.Conn, raw []j return fmt.Errorf("EVENT expects 2 elements") } - if err := h.requireAuth(ctx, conn, true, state); err != nil { - status = "error" - return err - } - - // Parse event to get ID for OK response + // Parse event first to get ID for error responses var event nostr.Event if err := json.Unmarshal(raw[1], &event); err != nil { status = "error" return fmt.Errorf("invalid event: %w", err) } + if err := h.requireAuth(ctx, conn, true, state); err != nil { + status = "error" + h.sendOK(ctx, conn, event.ID, false, err.Error()) + return nil + } + if state.authenticatedPubkey == "" && h.authConfig != nil && h.authConfig.WriteEnabled { status = "unauthenticated" h.sendOK(ctx, conn, event.ID, false, "auth-required: authentication required") @@ -283,7 +284,8 @@ func (h *Handler) handleEvent(ctx context.Context, conn *websocket.Conn, raw []j } if !h.limiter.Allow(identifier, "EVENT") { status = "rate_limited" - return fmt.Errorf("rate limit exceeded") + h.sendOK(ctx, conn, event.ID, false, "rate-limited: slow down") + return nil } } @@ -558,7 +560,7 @@ func (h *Handler) handleAuth(ctx context.Context, conn *websocket.Conn, raw []js state.authenticatedPubkey = authEvent.PubKey log.Printf("WebSocket client authenticated: %s", authEvent.PubKey[:16]) - h.sendOK(ctx, conn, authEvent.ID, true, "") + // Don't send OK for AUTH - it's not an EVENT return nil } -- cgit v1.2.3