Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebSocket new features #27

Open
MuratovBektur opened this issue Apr 3, 2022 · 5 comments
Open

WebSocket new features #27

MuratovBektur opened this issue Apr 3, 2022 · 5 comments

Comments

@MuratovBektur
Copy link

MuratovBektur commented Apr 3, 2022

Sorry for my english. I'm just a fan of web technology

WebSocket has not been updated for more than 10 years. And here's what I think you can do in the following versions of WebSocket and/or WebSocketStream:

1) WebSocket custom type as variant we can set new opcode in frame and in next frames send custom type string. Server-Sent Events can send custom type

const socket = new WebSocket(URL)
socket.addEventListenter('custom-type', handler)

2) In WebSocket send method first arg must be custom type and second arg must be data which we want send

const user = {
  name: 'John',
  age: 18           
}

const socket = new WebSocket(URL)
socket.send('custom-type', JSON.stringify(user))

3) In WebSocket send method auto convert to JSON for object, array or null

const user = {
   name: 'John',
   age: 18           
}

const socket = new WebSocket(URL)
socket.send(user)

4) Client ping method for checking is we connected to server

const socket = new WebSocket(URL)
socket.ping()

5) Add static property WebSocket.VERSION (for checking - is support options in a current version)

if (!WebSocket.VERSION) {
    // code for old browser
}
else if (WebSocket.VERSION === 14)  {
    // code for browser which support 14 version
}

6) Use options object as second argument for WebSocket constructor

const socket = new WebSocket(URL, options)

// options can has below properties
// a) reconnectInterval - reconnect to server if close type isn't was a clear. if this parameters  isn't  seted, so never reconnect
// b) pingInterval - auto send ping
// c) protocol - protocol name
// d) protocols - protocols names in array string. Options doesn't contain protocol and protocols, so we must call error if options // has both property 
@ricea
Copy link
Collaborator

ricea commented Apr 6, 2022

  1. I'm not sure I fully understand this proposal. How would "custom-type" be set in a WebSocket frame? Changes to the protocol would require an update to the RFC, which is complicated because the working group that produced it has been dissolved.
  2. This API is problematic because the meaning of the first argument would have to depend on the number of arguments. While it's possible to define it this way, I think it's counterintuitive and goes against usual practice. It would be more usual to send the payload as the first argument, and have an options object as the second argument.
  3. Probably has backwards-compatibility issues. Also, I think send(JSON.stringify(user)) more clearly states the intent.
  4. I've thought about it, but I've come to the conclusion that application-level pings are better, since they verify that your application is alive and not just your WebSocket stack.
  5. I'd rather not change the protocol version unless we really have to. Supporting multiple versions is a big maintenance burden. For new features in the JavaScript API, it's better to detect the specific feature you need, as sometimes browsers lie.
  6. Maybe. But we'll probably add new features to WebSocketStream first.

@MuratovBektur
Copy link
Author

MuratovBektur commented Apr 6, 2022

Thank you for replying. It would be good if WebSocket and WebSocketStream evolve in parallel since I think many applications do not need all the power of WebSocketStream. It would be great if WebSocket supported auto reconnection, auto ping checking at a user-defined time, and also a custom type. Please discuss with your team about custom type as there are many crutches and think many would like to have built-in user type support

@prettydiff
Copy link

Item number 4 is actually a really good idea. According to RFC 6455 when one end of the socket receives a ping that end is expected to send a pong. Since these are control frames they can be intermixed with data frames without conflict or collision.

There are sufficient controls in place with something like Node that you can make a best guess determination on the health of a socket using a ping/pong round trip, but there is no access to control frames or frame headers within the browser so you are completely at the mercy of the browser that may not share the same concerns as the application maintainer.

I would recommend this feature as follows (TypeScript):

type pingCallback: (error:Error) => void;
type ping:(ttl:number, callback:pingCallback) => void;

This method would require a TTL (time to live) and a callback.

  • The ttl argument would be a number representing time in miliseconds.
  • The callback would contain error argument that returns an Error object type on connectivity failure or when exceeding the TTL. Otherwise the error argument would return null.

Example:

socket.ping(50, function (err) {
    if (err === null) {
        console.log("Socket is healthy");
    } else {
        console.log(err);
    }
});

@ricea
Copy link
Collaborator

ricea commented Aug 29, 2022

The ping() method is possible, but we should use modern API patterns, ie. promises instead of callbacks, AbortSignal instead of timeouts. So the above example would look something like

try {
  await socket.ping(AbortSignal.timeout(50));
  console.log("Socket is healthy");
} catch (err) {
  console.log(err);
}

@prettydiff
Copy link

prettydiff commented Aug 29, 2022

Try/catch breaks compilation in the immediate scope, so its generally not considered a best practice in high performance code. Promise chains offer a non-breaking catch which is better, but promise chains (then methods) impose a restrictive linear flow where such restrictions are not present with callbacks.

The AbortSignal API is for imposing a breaking halt between the DOM and execution of an event handler such that the event maybe arbitrarily cancelled whether by timeout or by an additional user interaction. Network interfaces should be isolated from external considerations, such as the DOM. A network health check could be called dynamically by a variety of means not in response from a DOM event.


Edit. Before this is over engineered to death here is all it needs to be successfull:

Operating scenarios:

  1. Socket is closed, execute the callback and pass in the corresponding error.
  2. Socket is open and TTL is achieved, execute the callback and pass in a timeout error.
  3. Socket is open and the corresponding pong is received before TTL, execute the callback and pass in null.

The only complexity in this is to identify the pong corresponding to the given ping. Control frames have 119 bytes of payload available for storing an identifier. Additionally, there are the 3 rsv bits that can be flipped to identify a frame apart from other similar frames and the rsv bits are not used by the browser at all. Then the server must merely return a pong with the same payload body (unmasked) and same rsv bits (if used). Everything is vanity and supplemental.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants