whatwg / websockets Goto Github PK
View Code? Open in Web Editor NEWWebSockets Standard
Home Page: https://websockets.spec.whatwg.org/
License: Other
WebSockets Standard
Home Page: https://websockets.spec.whatwg.org/
License: Other
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.
Almost Everything is in the title ;-)
ReadableStream from the Stream API is already used in the Fetch API
Streams were also considered for the UDP TCP Socket API via readable
and writable
UDPSocket
and TCPSocket
properties.
Web Sockets is probably one of the APIs for which such stream API would be the most pertinent
"The |Sec-WebSocket-Protocol| header field MUST NOT appear more than once in an HTTP response."
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:
const socket = new WebSocket(URL)
socket.addEventListenter('custom-type', handler)
const user = {
name: 'John',
age: 18
}
const socket = new WebSocket(URL)
socket.send('custom-type', JSON.stringify(user))
const user = {
name: 'John',
age: 18
}
const socket = new WebSocket(URL)
socket.send(user)
const socket = new WebSocket(URL)
socket.ping()
if (!WebSocket.VERSION) {
// code for old browser
}
else if (WebSocket.VERSION === 14) {
// code for browser which support 14 version
}
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
Edit: Formatting and add a couple other codes.
In https://websockets.spec.whatwg.org/#dom-websocket-close, the first step is this:
- 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.
Hey,
Following this: https://bugs.chromium.org/p/chromium/issues/detail?id=695932#c3
I think its important to expose somehow the HTTP status code from the initial handshake of the WebSocket connection to user-land JS to be able to differentiate between different cases such as invalid authentication, rate-limiting, etc.
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.
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.
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.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.)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.
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 = []);
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:
web-platform-tests/wpt#40632 looks incorrect to me. The equivalent of a network error should happen, which doesn't end up yielding an exception, but rather an error event.
Authenticate with a vm that is spun up automatically and does not have a certificate signed by valid certificate chain.
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.
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.
Apparently Chrome accepts HTTP/1.0 and Firefox as per https://bugzilla.mozilla.org/show_bug.cgi?id=1767376 rejects. It would be good if the standard said something about this and this was tested.
Perhaps the HTTP WG would also like to know this happens in the wild.
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.
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
.init
parameter of fetch.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.
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.
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.
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.
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.
As per whatwg/fetch#514 and the more detailed discussion in web-platform-tests/wpt#5213 WebSockets may require detailed cookie processing we need to sort through as that's not currently covered.
The test Create-protocols-repeated-case-insensitive.any.js implies that subprotocols are to be compared case-insensitively, however none of the browsers tested by that site pass the test.
I have pored through this standard and RFC6455 and can find no reference to them being case-insensitive.
The WebSocket constructor is definited to run as final step the following:
- 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).
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 .
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:
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.
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?
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:
fetch()
with Authorization
before opening the web socket connection.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).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.