Code Monkey home page Code Monkey logo

websockets's People

Contributors

annevk avatar domenic avatar reububble avatar ricea avatar yutakahirano avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

websockets's Issues

What should happen when the WebSocket constructor is called for a global whose document is not current?

As far as I can tell, the spec requires that the constructor work and return a websocket, and this websocket try to connect and whatnot. But I don't see what would ever shut down that connection, once established. Websocket connections are normally shut down during navigation, but only the ones corresponding to the global being unloaded, and we're past that step for this global.

See http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=4721 for a kinda testcase, though it's using a websocket to something that doesn't speak websocket, so doesn't actually end up with a connection.

In terms of UA behavior, Firefox throws from the constructor in this situation. Chrome creates the object, but it behaves in what look like spec-violating ways (e.g. transitions from the CONNECTING state to the CLOSED state without firing a "close" event as far as I can tell). I haven't tested other UAs, or what happens if the URL used points to an actual websocket endpoint.

WebSocket new features

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 

Is there a reason the only 1xxx close code allowed is 1000?

Edit: Formatting and add a couple other codes.

In https://websockets.spec.whatwg.org/#dom-websocket-close, the first step is this:

  1. If code is present, but is neither an integer equal to 1000 nor an integer in the range 3000 to 4999, inclusive, throw an "InvalidAccessError" DOMException.

I can understand 1000 being allowed as well as some being disallowed for security (like 1002 and 1005) and/or technical (like 1001 and 1006) reasons. But some of the other 1xxx status codes seem like they'd make sense for a client to return back to the server:

  • 1008 is semantically analogous to a 4xx HTTP error. From the RFC (emphasis added):

    1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the policy.

    One potential use case here is a client receiving an invalid message from the server that leaves the client in an invalid connection state and the only safe way to proceed is to close the connection. (Essentially just not trusting the server.)

  • 1011 is semantically analogous to a 5xx HTTP error. From the RFC (emphasis added):

    1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.

    One potential use case here is a client being left in a fatally erroneous state and seeing it safer to disconnect than to continue.

  • 1003 would be useful at the very least for cases where the client can only accept binary frames or can only accept text frames. Even if this isn't explicitly supported as a user status code, it'd be nice to at least be able to maybe declare it in the constructor so it can be handled appropriately.

  • 1013 would be useful for signaling client-side timeouts, in case the client is doing active pinging of the server to ensure server availability (relevant for more real-time use cases like multiplayer games).

Of course, I may be mistaken and misinterpreting the RFC here. My current workaround is to specify these in the 3xxx range instead of the standard 1xxx.

Refactoring WebSocket connections

In whatwg/fetch#1244 @ricea started a draft of how WebSockets could take partitioning better into account and maybe also share more logic with Fetch's connection infrastructure. That work is still important, but now needs to happen here as whatwg/fetch#1516 will remove the parts this specification took over from Fetch.

I didn't want to move whatwg/fetch#1243 over as it seems good to keep track of this issue on the Fetch side and the discussion there is no longer as relevant as a number of decisions have already been made.

Expose ping/pong mechanism for user integration

In https://websockets.spec.whatwg.org/#ping-and-pong-frames, it says the following:

The WebSocket protocol defines Ping and Pong frames that can be used for keep-alive, heart-beats, network status probing, latency instrumentation, and so forth. These are not currently exposed in the API.

User agents may send ping and unsolicited pong frames as desired, for example in an attempt to maintain local network NAT mappings, to detect failed connections, or to display latency metrics to the user. User agents must not use pings or unsolicited pongs to aid the server; it is assumed that servers will solicit pongs whenever appropriate for the server’s needs.

Prior discussion in https://www.w3.org/Bugs/Public/show_bug.cgi?id=13104 states ping/pong functionality is only meant to be a keepalive mechanism, but this interpretation is explicitly contradicted by the note in RFC 6455 section 5.5.2: (emphasis added)

NOTE: A Ping frame may serve either as a keepalive or as a means to verify that the remote endpoint is still responsive.

There is some web dev need for active server responsiveness checks as well, and the usual workaround where the web dev controls both client and server is to use special data frames to implement that at a higher level, which is at best just wasteful and at worst just plainly wrong depending on the size of typical messages received.


Concretely, I have a suggestion: add a responsivenessCheck: {issueAfter, timeout} option for the WebSocket constructor to implement this in a way that gives the web developer what they need and.

  • UAs must send a ping frame with UA-dependent data after at least responsivenessCheck.issueAfter milliseconds of no data received from the underlying socket and must terminate the connection abnormally if no frame is received by at least responsivenessCheck.timeout milliseconds.
  • Any frame resets the timer regardless of type, and upon the timeout triggering, a close event should be fired against the web socket with a status of 1006, consistent with the existing spec's warning here, if no data has been received by the time the timeout triggers and the web socket is still open. (This extra condition avoids the race condition of timeout task schedule -> data/close received -> timeout task execute.)
  • A UA should send a close frame to the server with a close code of 1008 upon disconnect, but it isn't required to.

The idea here is to offer a mechanism that tracks connection responsiveness correctly, so users aren't having to hack their own (likely inadequate and/or inaccurate) versions of this for things like multiplayer games and real-time chat.

Allow dictionary as second param in WebSocket constructor

This would allow server environments (specifically talking about nodejs/undici) that implement WebSocket some flexibility, for example, to add custom headers, etc. While we could change it on our side, it would be incompatible with other implementations. Similarly, it'll cause type issues with people who use typescript in cross-env packages (ie. nodejs/undici#1943).

Proposed change:

dictionary WebSocketInit {
  protocols: DOMString or sequence<DOMString>
}

interface WebSocket : EventTarget {
  constructor(USVString url, optional (DOMString or sequence<DOMString> or WebSocketInit) options = []);

WebSocket and relative URLs

Relative URLs are good, and most assets on the web can enjoy usage of them (images, videos, flash objects, EventSource, etc), but the WebSocket constructor does not support them.

Presumably this is due to requiring a ws or wss protocol, but I would pose that using http and https is actually fine for WebSockets, as it accurately represents the method by which they acquire a connection.

So all together:

  • Allow WebSocket to use http(s) protocol URLs
  • If not, still allow relative URLs by mapping the protocol instead of throwing

serverCertificateHashes

What problem are you trying to solve?

Authenticate with a vm that is spun up automatically and does not have a certificate signed by valid certificate chain.

What solutions exist today?

For webtransport, the option "serverCertificateHashes" exists, which will be soon be supported by at least two major browser engines.
For now, in environments with only TCP/IP support the alternative transports over http/2 are not implemented yet and one major browser has no webtransport support at all. So if websockets are used as fallback, they need a different certificate chain than the webtransport, if serverCertificateHashes would be used.

How would you solve it?

Support for serverCertificateHashes, may be use as alternative second argument to the WebSocket contructor an options object:

new WebSocket(url, {protocols: [...], serverCertificateHashes: [...]}
```
this would allow to run the WebTransport fallback in the same way as the WebTransport connection.

### Anything else?

Depending on the implementation side effects to the fetch api need to be considered.

Configure credentials of cookies for WebSocket

Proposal

Add an option to WebSocket to configure the sending of cookies in the HTTP handshake with the same behavior as the credentials option of fetch.

API

The WebSocket constructor could take an init parameter: new WebSocket (input, init = {}) which would contain the :

  • protocols: Either a single protocol string or an array of protocol strings.
  • credentials: The request credentials you want to use for the request: omit, same-origin, or include.
  • and maybe other options such as the init parameter of fetch.

Other languages

Clients in other languages allow you to directly modify the request headers (and thus the cookies).

fetch doesn't allow you to modify the cookies (probably security related), that's why I propose to add the credentials option.

Motivation

I develop a webextension that connects to a WebSocket server. The server doesn't accept requests bigger than 1024 bytes. But other services that are on the same domain name (with different ports), set cookies that are sent unnecessarily to the WebSocket and increase the size of the request. I would like to add the option { credentials: "omit" } to not send cookies.

And if options are useful for fetch, they should be useful for WebSocket HTTP handshake.

Related links

WebSocket - enable backpressure support by supporting Streams integration

Filed from TAG review of WebSocket in HTML spec: w3ctag/design-reviews#268

WebSockets predate Streams in the platform, but there's no reason why support for Streams can't be grafted into WebSockets! The primary motivations to add Stream support is to enable convenient backpressure management for applications.

Lack of backpressure is unfortunate. If you can't keep up with the network you run out of CPU or RAM.

Such integration would need to rationalize how the onmessage event would be impacted.

Support for custom headers for handshake

Hi,

please consider adding ability to add custom headers for handshake.
In RFC6455 there one interesting point:

The request MAY include any other header fields, for example,
cookies [RFC6265] and/or authentication-related header fields
such as the |Authorization| header field [RFC2616], which are
processed according to documents that define them.

I've found an example how to add custom header to handshake: https://blog.heckel.xyz/2014/10/30/http-basic-auth-for-websocket-connections-with-undertow/ but this is for Java and unfortunately isn't possible in HTML5.

When searching over the net I found many places question about this option, for example:
sta/websocket-sharp#22
https://stackoverflow.com/questions/4361173/http-headers-in-websockets-client-api/4361358#4361358
aspnet/SignalR#888

For example in Python this is possible https://stackoverflow.com/questions/15381414/sending-custom-headers-in-websocket-handshake. Other languages also support this. Last place missing is the browser.

Please consider adding this into specification. Having this even as a draft would allow us to consider browser vendors to add support for it.

If this is incorrect place for adding request about specification please forgive me and please point me to right place.

Use current settings object instead of relevant settings object

https://websockets.spec.whatwg.org/#dom-websocket-websocket says

Let client be this's relevant settings object.

client is used for base URL for parsing relative URLs. This was introduced in #45

I think "relevant" should be "current". See web-platform-tests/wpt#39978 (comment)

WebSocket spec says to use the relevant settings object, but going by the example in https://html.spec.whatwg.org/multipage/webappapis.html#realms-settings-objects-global-objects there's no way to test for the relevant settings object for a constructor (vs a method), since you can't use .call() with a constructor.

I used current instead, like Workers, but this needs a spec change.

Unclear wording for "in parallel" while running WebSocket constructor

The WebSocket constructor is definited to run as final step the following:

  1. Run this step in parallel:

Establish a WebSocket connection given urlRecord, protocols, and client. [FETCH]

and the "in parallel" is defined as

To run steps in parallel means those steps are to be run, one after another, at the same time as other logic in the standard (e.g., at the same time as the event loop).

which allows interpretation that the WebSocket constructor can start a new thread to establish the WebSocket connection that runs in parallel with JavaScript engine and JavaScript event loop without syncronization of any kind.

However, typical usage of WebSocket is like

ws = new WebSocket("wss://...");
ws.on("error", function (error) { ... });

so in theory the first line could run the constructor which runs in parallel thread without any syncronization and fires the "error" event before the second line is executed. This would obviously result to missing that error event.

I think the logic is supposed to be that either the WebSocket connection is created via JS event loop syncronization or the "error" event is fired via the JS event loop to syncronize the event handling with the JS code. However, I fail to see any requirement to do this in the wording of the related specs. I'd expect some process to include "queue a task" step, possibly the code that handles network error before the connection is established and event open is triggered (which does have the step to queue a task).

Give hints about HTTP/2 and HTTP/3 support when opening a WebSocket

WebSockets over HTTP/2 are not supported by many servers. There can be different reasons for that. Support for WebSockets over HTTP/3 is a new IETF draft.

The clients do not know if WebSockets are supported by a HTTP/2 or HTTP/3 server until the TLS handshake is done and SETTINGS frames are exchange. If WebSockets are not supported the clients need to fall back to HTTP/1.1 and open a new connection. This adds a delay, trying HTTP/2 and HTTP/3 would add even more delay.

An option to eliminate trying HTTP/2 and HTTP/3 is to have hint from developer when WebSocket is created whether the servers support the feature. And if they do not support the feature, the client will use HTTP/1.1 directly.

@annevk suggested to have a way to ask for a dedicated connection, that would mean use HTTP/1.1 .

@ricea and @youennf may be you have some feedback.

Queueing/Throttling

According to MDN the send method enqueues data of supported types for transfer, however the data is not queued across a variety of user agents. When data is not queued a transmission payload is abandoned from transfer if in conflict with a more recent transmission.
This is because a websocket is a single socket and RFC 6455 does not permit the interlacing of data frames. With some additions to websockets in the browser developers can write their own userland queue.

According to RFC 6455 a transmission is complete when both the first bit of the first byte of a payload fragment is 1 and at the byte size specified by the payload size bytes of the frame header. I can account for this in Node.js and write my own queue implementation at both the sender and receiver to ensure that transmissions do not conflict or interlace and also account for instances when frame headers are separated from frame bodies or if two separate frames are concatenated into a single transmission.

The browser does not provide me the capability to read frame headers on incoming transmissions, the message event, so I cannot solve for this problem according to the definitions provided in RFC 6455. My solution to this problem is to two-fold:

  1. Add a new readyState value - 4 - transmitting
  2. Add a new event - finish

The ready state value indicates the channel is open and actively writing data to the socket. The send method changes a socket's ready state from 0, open, to 4, transmitting. When the transmission completes the ready state returns to 0 and the event finish executes.

This is beneficial for circumventing long polling. If, for example, a given socket were used for a media transmission that socket may be sending binary data for an extended and undetermined length of time. It would frustrate the user if that transmission fails because the socket executes another send method on a user agent that isn't properly enqueueing transmissions. The ideal user experience is for the application to know the current state of the socket so that it may open an additional socket for trivial data transmissions. Even on user agents that are properly enqueue transmissions it may be a better user experience to open a parallel socket as the needs of the user demand, but there is not an automated means of knowing when such actions are appropriate.

WebSocket options object

Coming from https://es.discourse.group/t/websocket-with-options-object/936:

There is currently no way of passing options except url and protocols to a WebSocket during instanciation. Setting up binaryType for example requires a second line:

const socket = new WebSocket(`ws://example.com`);
socket.binaryType = "arraybuffer";

I think it would be nice to be able to pass options as an object during instanciation:

const socket = new WebSocket(`ws://example.com`, {  binaryType: "arraybuffer" });

If one wants to pass protocols as well, it is easily possible with an object

const socket = new WebSocket(`ws://example.com`, { binaryType: "arraybuffer", protocols: [] });

Or is there a compelling reason why this isn't a thing?

Investigate 401 handling for WebSocket

This is a follow-up to whatwg/fetch#565 and whatwg/fetch#761 (comment) in particular.

It'd be good to write more tests that cover the various scenarios:

  1. Not authenticated, server replies with 401
  2. Authenticated via fetch() with Authorization before opening the web socket connection.
  3. 2, but server replies with a 401 anyway.
  4. More?

Not sure all of those are easy to do in web-platform-tests given that authentication entries likely don't cross ports...

And review the algorithms in the standard again to ensure no prompting can take place ever (and maybe check again if implementations have the necessary bugs if they don't implement that).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.