ReactiveX/rxjs

WebSocketSubject does not provide code on close

ncowama opened this issue · 0 comments

Describe the bug

When closing the socket as part of subscription teardown, the implementation calls _socket.close():

https://github.com/ReactiveX/rxjs/blob/7.8.1/src/internal/observable/dom/WebSocketSubject.ts#L380-L382

Because there is no status code, WebSocket defaults to status code 1005 - No Status Rcvd ("Indicates that no status code was provided even though one was expected."). Given that the close is expected, the status should be 1000 - Normal Closure. Otherwise the consumer might treat status other than 1000 as error state, which is incorrect.


There is a related issue: #4087 with a proposed solution to call .error({ code }).

It's possible to work around this with a side-effect calling wsSubject.error({ code: 1000 }), but it's not ideal

disabled
  .pipe(
    tap({
      next: (disabled) => {
        if (disabled) {
          wsSubject.error({ code: 1000 });
        }
      },
    }),
    switchMap((disabled) => iif(() => !disabled, ws, EMPTY))
  )

Expected behavior

socket is closed with code=1000 when subscription is closed. Or a mechanism to define status code for the socket.close call.

Reproduction code

import { BehaviorSubject, EMPTY, iif, retry, switchMap } from 'rxjs';
import { webSocket } from 'rxjs/webSocket';

const disabled = new BehaviorSubject(false);
const wsSubject = webSocket({
  url: 'wss://socketsbay.com/wss/v2/1/demo/',
  openObserver: {
    next: () => console.log('Open'),
  },
  closeObserver: {
    next: (event) => console.log(`Closed, code=${event.code}`),
  },
});
const ws = wsSubject.pipe(retry({ count: 3, delay: 500 }));

disabled
  .pipe(switchMap((disabled) => iif(() => !disabled, ws, EMPTY)))
  .subscribe((value) => console.log(value));

setTimeout(() => {
  console.log('disabled=true');
  disabled.next(true);
}, 1000);

setTimeout(() => {
  console.log('disabled=false');
  disabled.next(false);
}, 2000);

// Output:
// Open
// disabled=true
// Closed, code=1005
// disabled=false
// Open

Reproduction URL

https://stackblitz.com/edit/rxjs-i5b8xv?file=index.ts

Version

v7.8.1

Environment

No response

Additional context

No response