Re: [hybi] Apples and Orangutans

Ian Hickson <ian@hixie.ch> Mon, 13 April 2009 00:11 UTC

Return-Path: <ian@hixie.ch>
X-Original-To: hybi@core3.amsl.com
Delivered-To: hybi@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id DC36C3A6BAF for <hybi@core3.amsl.com>; Sun, 12 Apr 2009 17:11:00 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -3.462
X-Spam-Level:
X-Spam-Status: No, score=-3.462 tagged_above=-999 required=5 tests=[AWL=-0.863, BAYES_00=-2.599]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id P0PbXNI9A7VI for <hybi@core3.amsl.com>; Sun, 12 Apr 2009 17:10:59 -0700 (PDT)
Received: from looneymail-a5.g.dreamhost.com (caibbdcaaaaf.dreamhost.com [208.113.200.5]) by core3.amsl.com (Postfix) with ESMTP id F3B8B3A6A2F for <hybi@ietf.org>; Sun, 12 Apr 2009 17:10:34 -0700 (PDT)
Received: from hixie.dreamhostps.com (hixie.dreamhost.com [208.113.210.27]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by looneymail-a5.g.dreamhost.com (Postfix) with ESMTP id B0540122541; Sun, 12 Apr 2009 17:11:44 -0700 (PDT)
Date: Mon, 13 Apr 2009 00:11:43 +0000
From: Ian Hickson <ian@hixie.ch>
To: Maciej Stachowiak <mjs@apple.com>
In-Reply-To: <1D801D05-C7F1-4DDC-8034-FAA458626F53@apple.com>
Message-ID: <Pine.LNX.4.62.0904122350370.10339@hixie.dreamhostps.com>
References: <49DEF171.4080506@mozilla.com> <A3699591-148C-4795-967A-6CDE23FE75F0@apple.com> <Pine.LNX.4.62.0904122230550.10339@hixie.dreamhostps.com> <71289452-5A19-48F4-9819-7FD9747EE9CA@apple.com> <Pine.LNX.4.62.0904122251070.10339@hixie.dreamhostps.com> <1D801D05-C7F1-4DDC-8034-FAA458626F53@apple.com>
Content-Language: en-GB-hixie
Content-Style-Type: text/css
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset="US-ASCII"
Cc: hybi@ietf.org
Subject: Re: [hybi] Apples and Orangutans
X-BeenThere: hybi@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: Server-Initiated HTTP <hybi.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/hybi>
List-Post: <mailto:hybi@ietf.org>
List-Help: <mailto:hybi-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=subscribe>
X-List-Received-Date: Mon, 13 Apr 2009 00:11:00 -0000

On Sun, 12 Apr 2009, Maciej Stachowiak wrote:
> > 
> > I don't understand why a 16bit integer solves the problem for TCP, but 
> > a string doesn't solve the problem for WebSocket. They seem exactly 
> > equivalent to me -- they identify the target of the connection, and by 
> > convention, the protocol that that target supports.
> 
> HTTP is a better analogy here than TCP in my opinion. The fact that TCP 
> only maps ports to protocols by convention is not so great - we have to 
> go to extra design effort to prevent cross-protocol attacks as a result.

WebSocket has built-in support for preventing cross-protocol attacks -- 
only trusted peers can send arbitrary data, everyone else is just 
disconnected before the server receives the data.

Why would HTTP be a better analogy? WebSocket really is just trying to be 
TCP for the Web. It doesn't really have anything in common with HTTP other 
than the handshake, and that's really a red herring.


> > Why couldn't we exect multiple chat services to use the same path for 
> > their chat server, in the same way that multiple chat services written 
> > on TCP use the same port?
> 
> I think that would be a poor design in the same way as relying on the 
> exact path of "/favicon.ico" or "/crossdomain.xml" is a poor design.

Fixed URLs are bad in HTTP because it causes people who don't know that 
the resources exist to try to obtain them. They're also a bad idea because 
HTTP is split across multiple users, but the fixed URLs are per-host.

With WebSocket the first point doesn't apply -- we aren't talking about 
people connecting to arbitrary hosts, we're talking about a convention by 
which someone can guess what protocol a server speaks.

The second point need not apply either, since we don't have to lock the 
entire path down, we can just say that the filename, or the extension, or 
whatever, is where you put the protocol you're willing to speak. So if you 
want to write a chat server that speaks WebSocketJabber, you can make it 
available at:

   ws://example.com/~jsmith/chat.wsj

...or some such.


> For one thing, it would mean you can't host multiple chat services on 
> the same host and port. That seems like an arbitrary limitation.

As shown above, this is not necessarily the case.


> Also, if your WebSocket service is running on the same host and port as 
> your web service, you may not have a free choice of what path to use, 
> since some may be taken.

That seems fine with just using the extension or filename part also.


> I think well-known paths are problematic and we should not design 
> WebSockets around using it for everything. I cited two examples above 
> where I believe you've stated on the record that well-known paths are a 
> design problem. What is different about WebSocket that makes relying on 
> well-known paths for everything a good idea?

What I'm advocating for is more like extensions that fixed paths, but even 
for fixed paths I don't believe the disadvantages they have in the realm 
of HTTP actually apply in the realm of WebSockets.


> It seems like extremely poor design to conflate the path (which 
> identifies a specific resource) with the type (which identifies the 
> *kind* of resource).

It's what pretty much every widely-used file system does. It's what 
authors understand. Content-Type has been pretty solidly shown to be a 
failed experiment, IMHO.


> > It's not really clear to me how we would expose the information in the 
> > API if we were to use something other than the path.
> 
> Exposing the information in the API would be trivial. And additional 
> callback, or a property on the WebSocket object guaranteed to be set by 
> the time the first message is received, would both work OK.

Current API:

   socket = new WebSocket('ws://example.com/chat.dcp');
   socket.onmessage = function (e) {
     if (e.data != 'DCP') {
       error('The server mysteriously stopped speaking DCP!');
       socket.disconnect();
     }
     socket.onmesage = chatHandler;
   }
   socket.postMessage('DCP');

Explicit API:

   socket = new WebSocket('ws://example.com/chat', 'DCP');
   socket.onprotocol = function (e) {
     if (e.data != 'DCP') {
       error('The server mysteriously stopped speaking DCP!');
       socket.disconnect();
     }
   }
   socket.onmesage = chatHandler;

It doesn't seem to gain us much.


> By comparison, XMLHttpRequest provides for type checking by exposing the 
> HTTP response headers. [...]
>
> It is true that most Web content authors don't currently check the type 
> of XMLHttpRequest responses, except perhaps implicitly by using 
> responseXML.

So why should we bother?


> However, until very recently there was no ability to 
> connect to an unknown service via XMLHttpRequest since cross-domain 
> support is a recent innovation that is still being deployed.

It's not like the people connecting to remote JSON resources using 
<script> ever considered that the remote script might not be JSON. They 
say "json" in the URL they connected to, and they assumed it would work.


> Browsers check types all the time however (even though in various cases 
> that information is not considered completely reliable). Browsers do not 
> rely on hardcoded well-known paths to identify the type of the resource, 
> and it's hard to imagine the Web working as well as it does if they did.

Browsers check types by sniffing more than anything, and rely on 
well-known paths quite a lot. I think it's a stretch to say that the check 
types "all the time". But this is academic, because the browsers are 
acting on the users' behalf, whereas these scripts are acting on the 
authors' behalf. As the subject line of this thread suggests, it's an 
apples and oranges comparison.


> One use case that we can foresee is a JavaScript library using WebSocket 
> to connect to a chat service using a well-known protocol (perhaps 
> someone will specify a protocol for Jabber over WebSocket). In such a 
> case, it is much more likely that the protocol type will be checked than 
> with hand-coded client code, since the library will want to report 
> errors to the content author in a reasonable way rather than return 
> garbage data.

Why is a trivial handshake not enough for this?


> Adding a protocol type would be a modest extension that is trivially 
> added to the protocol and client-side API. It would add very little 
> complexity to the case of connecting to a known service, but creates for 
> the possibility of a sane way of connecting to unknown services.

I don't understand what value it adds.

For custom protocols, authors aren't going to want to worry about the 
details of an additional handshake after the one we require now. Why add 
anything at all, when you can do it all -- if you want it -- over the 
regular WebSocket channel?

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'