[whatwg] Web Sockets
Shannon
shannon at arc.net.au
Tue Jul 22 23:17:55 PDT 2008
Philipp Serafin wrote:
>
>> Asynchronous: Requests and responses can be pipelined, meaning requests and
>> responses can be transmitted simultaneously and are queued.
>>
>
>
> I think the problem is that this definition of "asynchronous" is very
> narrow. Yes, you don't need to wait for a request to finish before you
> issue a new one. But you'd still be bound to HTTP's request/response
> scheme in general.
>
WebSockets uses HTTP so it is hardly immune to the request/response
behaviour of its underlying protocol (including the stream nature of TCP).
Besides this statement appears to be based on the assumption that the
server MUST wait for additional client requests to send each "message".
However the specification allows the server to send "chunked" or
"multipart" data in a variety of ways so full asynchronous communication
is acheivable by making the response chunks part of one long HTTP
multipart response and allowing the javascript API to access the
incoming data while the response is incomplete. It can be simplified for
the end-user by allowing the raw server response to be read by bytes,
lines or "parts". If you need more channels (ie, to pass messages while
sending a large file) then you simply open more WebSockets and let the
server handle multiplexing via cookies or message ids.
> However, web authors might want to employ other schemes as well, for
> example server-sided asynchronous notifications ("pushing"),
>
Client opens a connection. handshakes, then leaves connection open
listening for "pushed" parts in the response stream.
> client-sided notifications that don't need to be replied
HTTP has a status code specifically for this purpose.
> or requests that can be answered out-of-order.
The order of data is controlled by the order it is sent by the
application. There is no requirement for the requests and
responses/parts to be synchronised. Especially if the server responses
consist of a single multi-part "response".
I'm not advocating against WebSockets, just its current definition. In
particular it tries to solve things that HTTP/1.1 already handles. I
believe we should be thinking of WebSockets as a Javascript API, not a
new communications protocol for the simple reason that HTTP is already a
very suitable and widely deployed protocol. What authors (especially
AJAX authors) are missing is a reliable way to use HTTP's existing
asynchronous connection support.
Here are my issues with WebSockets as currently defined:
1.) Request must have a <scheme> component whose value is either "ws" or
"wss"
The "scheme" should be HTTP(S). WebSockets should be the API.
2.) The message event is fired when when data is received for a
connection.
What "data"? A byte, a line, a chunk, the whole response? The spec isn't
clear. I'd also recommend adding a connection.read( max_bytes ) method
as used by Python and most languages to let the author receive bytes at
a frequency appropriate to the application (eg, a game might want to
frequently poll for small updates).
3.) If the resulting absolute URL has a <port> component, then let port
be that component's value; otherwise, if secure is false, let port be
81, otherwise let port be 815.
No, no, no! Don't let paranoia override common sense. Not all websocket
applications will have the luxury to run on these ports (multiple web
servers, shared host, tunnelled connections, 2 websocket apps on one
host, etc...).
4.) The whole handshake is too complex.
There are many firewalls, proxies and servers that legimately insert,
change, split, or remove HTTP headers or modify their order. This is
also likely if the service being provided sits on top of a
framework/server (such as Coldfusion/IIS). Also what happens if HTTP/1.2
is sent? These will break the WebSocket handshake as currently defined.
rfc 2616 section 3 says: The version of an HTTP message is indicated by
an HTTP-Version field in the first line of the message.
HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
How many non-http servers send this? Probably none. I recommend the
handshake simply read about 256 bytes of the server response and check
that it contains a valid HTTP version field and one or more valid HTTP
headers and optional end-of-headers marker. If ALL headers semantically
validate (ie, with the regex [A-Za-z-]: \s(.*?)\r\n) then it is
reasonably safe to assume it is a real HTTP or WebSockets service. If
the headers validate then the client repeats the process until the
message body is reached. At this point we check our collected headers
for at least one "Accept" header containing "WebSocket" (assuming that
being a "WebSocket" rather than a basic pipelined HTTP connection is
even useful).
5.) URI parsing specification
The current proposal spells out the URI/path parsing scheme. However
this should be treated EXACTLY like HTTP so the need to define it in the
spec is redundant. It is enough to say that the resource may be
requested using a GET or POST request. Same with cookie handling,
authorization and other HTTP headers. These should be handled by the
webserver and/or application exactly as normal, there is no need to
rewrite the rules simply because the information flow is asynchronous.
6.) Data framing specification
Redundant because HTTP already provides multiple methods of data segment
encapsulation including "Content-Length", "Transfer-Encoding" and
"Content-Type". Each of these have sub-types suitable for a range of
possible WebSocket applications. Naturally it is not necessary for the
client or server to support them all since there are HTTP headers
explicitly designed for this kind of negotiation. The WebSocket should
however define at least one fallback method that can be relied on (I
recommend "Content-Length", "Transfer-Encoding: chunked" and
"Content-Type: multipart/form-data" as MUST requirements).
7.) WebSockets needs a low-level interface as well
By "dumbing down" the data transfer into fired events and wrapping the
data segments internally the websocket hides the true communication
behind an abstract object. This is a good thing for simplicity but
extremely limiting for authors wanting to fine-tune an application or
adapt to future protocols. I strongly recommend that rawwrite() and
rawread() methods be made available to an OPEN (ie,
authenticated/handshaked) websocket to allow direct handling of the
stream. It would be understood that authors using these methods must
understand the nature of both HTTP and websockets. In the same way a
settimeout() method should be provided to control blocking/non-blocking
behaviour. I can't stress enough how important these interfaces are, as
they may one day be required to implement WebSockets 2.0 on "legacy" or
broken HTML5 browsers.
8.) Origin: / WebSocket-Origin:
Specifying clients allowed to originate a connection is a disaster
waiting to happen for the simple reason that sending your origin is a
privacy violation in the same vain as the referrer field. Any
open-source browser or privacy plugin will simply disable or spoof this
since it would allow advertising networks to track people by ad-serving
via websockets. Such tracking undermines the security of anonymising
proxies (as the "origin" may be a private site or contain a client id).
Using origin as a required field essentially makes the use of "referrer"
mandatory. If a websocket wants to restrict access then it will have to
use credentials or IP ranges like everything else.
9.) WebSocket-Location
The scenario this is supposed to solve (that an application makes a
mistake about what host it's on and somehow sends the wrong data) is
contrived. What's more likely to happen is that a server application has
trouble actually knowing its (virtual) hostname (due to a proxy,
mod_rewrite, URL masking or other legitimate redirect) and therefore NO
clients can connect. It isn't uncommon for the host value passed to a
CGI script and the hostname returned by the environment (ie, via uname
or OS library) to conflict. Then there is the matter of an SSL
connection (no host header available). I'm having trouble determining
why this should even matter. I suspect most simple applications/wrappers
will just echo back the host header sent by the client so if a mistake
is made it's likely to go unnoticed anyway.
10.) To close the Web Socket connection, either the user agent or the
server closes the TCP/IP connection. There is no closing handshake.
HTTP provides a reliable way of closing a connection so that all parties
(client, server and proxies) know why the connection ended. There is no
reason for websockets to not follow this protocol and close the
connection properly.
In conclusion, the current specification of WebSockets re-invents
several wheels and does so in ways that are overly complex, error-prone
and yet seriously limited in functionality. The whole concept needs to
be approached from the position of making HTTP's features (which are
already implemented in most UAs) available to Javascript (while
preventing the exploit of non-HTTP services). I do not believe this is
difficult if my recommendations above are followed. I do not wish to be
overly critical without contributing a solution, so if there are no
serious objections to the points I've made I will put time into
reframing my objections as a compete specification proposal.
Shannon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20080723/ac285de0/attachment.htm>
More information about the whatwg
mailing list