| 226 | } |
| 227 | |
| 228 | func TestWSDataBeforeCloseFrame(t *testing.T) { |
| 229 | mr := &fakeReader{ch: make(chan []byte, 1)} |
| 230 | defer mr.close() |
| 231 | r := wsNewReader(mr) |
| 232 | |
| 233 | p := make([]byte, 100) |
| 234 | |
| 235 | // Simulate what happens when a NATS server sends an -ERR message |
| 236 | // followed by a WebSocket close frame in the same TCP read. |
| 237 | // This is the case described in https://github.com/nats-io/nats.go/issues/2024: |
| 238 | // the server sends "-ERR 'Authorization Violation'\r\n" as a text frame, |
| 239 | // immediately followed by a WebSocket close frame. The data frame must |
| 240 | // be returned to the caller before the close frame's io.EOF. |
| 241 | errMsg := []byte("-ERR 'Authorization Violation'\r\n") |
| 242 | |
| 243 | // Binary frame (final=true) with the error message. |
| 244 | mr.buf.Write([]byte{byte(wsBinaryMessage) | wsFinalBit, byte(len(errMsg))}) |
| 245 | mr.buf.Write(errMsg) |
| 246 | // Close frame with status 1000 and body "Authentication Failure". |
| 247 | closeBody := "Authentication Failure" |
| 248 | closePayloadLen := 2 + len(closeBody) // 2 bytes for status + body |
| 249 | mr.buf.Write([]byte{byte(wsCloseMessage) | wsFinalBit, byte(closePayloadLen)}) |
| 250 | // Status code 1000 (normal closure) in network byte order. |
| 251 | mr.buf.Write([]byte{0x03, 0xE8}) |
| 252 | mr.buf.WriteString(closeBody) |
| 253 | |
| 254 | // First Read should return the -ERR data, not an error. |
| 255 | n, err := r.Read(p) |
| 256 | if err != nil { |
| 257 | t.Fatalf("Expected data to be returned before close, got error: %v", err) |
| 258 | } |
| 259 | if !bytes.Equal(p[:n], errMsg) { |
| 260 | t.Fatalf("Expected %q, got %q", errMsg, p[:n]) |
| 261 | } |
| 262 | |
| 263 | // Second Read should now return the deferred io.EOF from the close frame. |
| 264 | n, err = r.Read(p) |
| 265 | if err != io.EOF { |
| 266 | t.Fatalf("Expected io.EOF, got n=%v err=%v", n, err) |
| 267 | } |
| 268 | if n != 0 { |
| 269 | t.Fatalf("Expected 0 bytes on close, got %v", n) |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | func TestWSParseInvalidFrames(t *testing.T) { |
| 274 | |