I like this, it seems so much more clean than SPDY, HTTP really should stay a text based protocol. My understanding for the design of SPDY was that by forcing TLS it ensured that any proxy server in the middle wouldn't interfere or be "confused" with the connection.
What would an existing proxy server (i.e. doesn't understand HMURR) do with a connection that looked like this?
That is I think one of the big problems with this suggestion.
The world is full of proxies and html-consuming tools that do not bother to check the version number, which would get horribly confused by this, and probably mangle the stream.
I was under the impression one of the reasons SPDY is so different is precisely to try to avoid problems with bad proxies. I'm not an expert on this unfortunately, but I'm sure that quite a few bits of the web-proxy standard involved getting around badly behaving proxies, and they had to do a few strange things.
Even if the tool does not check the version number in the request, wouldn't any proxied response contain a HTTP/1.0 or HTTP/1.1 header? In that case, the client will see all but the first request in a connection stands no chance of being fulfilled, and fall back to HTTP/1.1 behaviour (perhaps caching a NO_HTTP_1_2 flag per hostname for a while)
Edit: Or also add an "Upgrade: slices" to the initial request, and if the expected response to the Upgrade: request is missing, continue with HTTP 1.1.
To be honest, I wouldn't be surprised. Proxies are precisely one of the reasons the WebSockets protocol has been changed to be such a pain in the ass compared to its original incarnation. I suggest checking out its original proposal and compare it to the draft RFC - it's rather enlightening.
It depends. A SOCKS proxy would continue to work perfectly; no changes needed there. But most production networks use HTTP proxying; assuming that they do not do MITM attacks (sometimes for legitimate inspection/compliance reasons) on the SSL traffic it will mean that HTTPS will continue to work perfectly too since that normally runs over a simple HTTP CONNECT Proxy which functions the same as a SOCKS proxy.
So that leaves the standard HTTP proxying. The HTTP proxy might treat the 2nd to nth request as being the payload of the HTTP request and may insert Content-Length headers. The HTTP proxy might filter out unknown HTTP headers (would be pretty bad; it's like the common example of where strict firewall admins tend to drop all ICMP packets). There will be security issues related to colliding Request-ID's and to the caching of it.
The standard HTTP pipelining is quite old and very well specified but afaik none of the major browsers implement it; I'm not sure why though. Maybe it depends on the lack of server support.
I do not propose to use Content-Range or 206 Partial Content because they already have a defined use. 206 Partial Content is used to response to a request for a specific range.
Okay, guess that makes sense; personally I wouldn't mind having this dual usage but maybe it would make the W3 spec people throw a hissy fit.
Interesting attempt I must say but I think it will be hard to actually get it out there. Too much legacy stuff in the way.
It's a bit like how for a really long time a lot of fancy new VOIP protocols were really hindered by the lack of proper NAT support leading to all these horrible workarounds to do NAT hole punching or more RFC's like STUN and TURN.
"personally I wouldn't mind having this dual usage but maybe it would make the W3 spec people throw a hissy fit."
They would be right to do so. 206 implies that the request is done. It is a very fundamental difference for 206 to stop meaning that. One can not just gloss over the fact that one of the connection may very well have closed the TCP stream. That's not a theoretical objection, that's a very pragmatic one.
It's unclear to me what advantages this proposal has over a HTTP/2.0 proposal using HTTP Upgrade. AFAICT, the client is unable to rely on HTTP/1.2 support in the first roundtrip. Therefore, it cannot begin utilizing the new proposed features. Relying on the HTTP/1.2 HTTP-Version within the Request-Line and Status-Line strikes me as less safe than trying to use the Upgrade header to attempt to upgrade to HTTP/2.0, as it seems much more likely for intermediaries to have broken HTTP-Version parsing than broken Upgrade support. In contrast with this proposal, when using the Upgrade header, there is much more freedom to change the wire level representation of the protocol. And if you're going to do HTTPS anyway, using TLS-NPN to negotiate a completely wire level representation (without an additional roundtrip over the TLS handshake roundtrip[s]) likewise enables more freedom to add features.
It seems like the main reason to prefer this proposal is if you do not want to write another parser for HTTP/2.0 and think that new features afforded by a different wire level representation are not worthwhile.
Another thing to note is that this proposal effectively adds on multiplexing without prioritization. Prioritization is fairly important, otherwise the client application has to do application layer throttling in order to reduce contention. Adding prioritization would help obviate the need to make the link utilization vs contention tradeoff.
I'm mostly disappointed to see a protocol that has thrived as textual (as have so many others over the years) get a binary layer added.
Some binary layers are helpful: TLS, for example, adds a nice generic encryption layer to connections. SPDY, on the other hand, has intimate knowledge of the operation of HTTP (which it needs to do header compression, for example). For example, the header compression dictionary is based on today's usage of HTTP with no provision for it to change over time.
It is a shame that features that are important to HTTP (multiplexing and priority) are not being added within HTTP itself.
I believe Patrick already well explained why this the binary representation is useful, so I won't bother addressing that.
I'd like to comment on your statement on the header compression dictionary. Firstly, your statement is only true for the initial header compression dictionary. Most of the improvement is achieved strictly through the use of compression at all, with very marginal gains from different compression algorithms or better initial dictionaries. If your implication is that intimate knowledge of HTTP is required for SPDY compression to work well, that is false. Please note the research at http://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf with the following conclusion: "This result suggests that zlib’s adaptive dictionary evolves to roughly an equivalent state after compressing the first header regardless of the content of the initial dictionary."
Can you clarify what you mean about features not being added within HTTP itself? Where are you drawing the line for "HTTP itself"? I'm curious, since the ideas behind SPDY have already been proposed for HTTP/2.0, and indeed the starting point for the HTTP/2.0 proposal used the SPDY draft, so I don't know what it means that important features aren't being added to HTTP itself.
When I think of HTTP I think of a text-based protocol not binary. I fully understand that SPDY has essentially been ratified as HTTP 2.0 given that the charter has been updated to be so close to SPDY itself. Thus at some point what I think if as HTTP will need updating to simply include SPDY and what I currently think of HTTP will be moot.
Transparent proxies, stupid antivirus software ... There's no end to the amount of crap that interferes with HTTP. These days, the only way one can get anything through is over SSL.
I don't really see the point. Spdy is already supported by major browsers more than this would ever have. Why have half the features when you can have them all? Also browsers would need new APIs to deal with getting the data from slicing as it doesn't seem to properly support something like web sockets (no multiplexing of the input, does spdy support web sockets?)
True, it doesn't help with web sockets but I think it could work very nicely with "Server-sent events"[1]. I believe that in almost all cases (Except gaming) where people are trying to use web sockets you can achieve the same result with SSE.
Patrick McManus (a Firefox developer) added the following comment directly on the blog posting. An underlying/implied point is that SPDY is already shipped [1].
"
Your premise seems to be that SPDY is a complex binary protocol and we don't need that achieve mux. I don't see much evidence for your complexity assertion - especially when compared with HTTP/1.
Consider the difference in finding the message boundaries of a SPDY message with an HTTP/1.1 one.
To process the SPDY message you
* buffer 8 bytes of data
* determine that it is a data packet by confirming (buf[0] & 0x80 == 0)
* determine the length of the data by ntohl(((uint32_t)buf)[1)& 0x00ffffff
* find out if there are more chunks to come by looking at (buf[4] & 1).
All done. It is very straightforward, efficient, well bounded, and testable.
Contrast that with parsing a HTTP/1 message.
* read "enough" data from the network. You don't know how much that is and if you read too much you have to implement some facility for "putting it back" so the next message can use it. This inevitably leads to streaming parsers and their inherent complexity and lack of efficiency.
* parse the headers so you can determine which message delimiter is being used. To parse the header you have to implement line folding, implement a tokenizer aware of various rules around quotation marks and colons, and adopt to a number of real-world variations in the use of line endings other than just CRLF. To do this you have to run a state machine against every byte of input rather than directly address fixed offsets.
* Implement strategies to deal with conflicts such "Content-Length: 42, 17" and "Content-Length: 95\r\nTransfer-Encoding: chunked\r\n"
* you need to implement an ascii to integer conversion routine to determine the status code because some status codes implicitly impact message delimiters (e.g. 304).
* now you have to implement no less than 5 message delimiting schemes - chunked encodings, EOF, content-length, implicit (304), and everyone's favorite multibyte/ranges.
* If you have content-length or a chunk you'll need to convert a text string to an integer again.. and http/1 doesn't bound the size of the text string so you'll either have a common bug with an overflow or you'll implement an undiscoverable constraint in your implementation leading to cases of failing interop.
* you'll still have exposure to a whole class of CRLF injection attacks inherent in the text format.
The binary framing is so much less complex and significant improvement. Sure, to the naked eye in a log it may not look that way but that is optimizing for all the wrong things and can be quite misleading - do you really interpret a HTTP header with line folding or \n\r instead of \r\n sequences correctly when eyeballing it?)
Now there certainly is some complexity in SPDY but it doesn't come, in my opinion, from the binary framing that you're talking about here. That is a a significant simplification over HTTP/1.
Developers of almost any skill level can write an HTTP/1.1 compatible implementation (and its fault tolerant enough that compatible-ish is ok). Soon we will live in a world with 3 or 4 HTTP/2.0 libraries and developers will have almost no knowledge of how the thing works under the hood.
It's not as if it needs to become opaque to developers. If people need a way to introspect a SPDY connection, someone will write a tool.
This is in the same vein as TCP, TLS, or DNS. Developers use these technologies all the time, and it exposes a simple interface to them, but all of them are quite complicated under the covers. I don't believe that Nagle's algorithm or the UDP framing for DNS is common knowledge amongst the majority of developers.
Similarly, SPDY or HTTP/2.0 will expose a simple interface to developers, but internally transport the content in an efficient, if somewhat inscrutable, manner.
While I appreciate the sentiment that HTTP is easy to understand as it stands, I'd rather not optimize for "developers of almost any skill level". While it would be totally OK for you to write a HTTP/1.1 parser as a toy, it would be somewhat crazy for you to use that implementation in a production scenario.
There, everybody uses a small set of implementations that have been vetted: Firefox, Chrome, Apache, Nginx, etc. These guys work extremely hard to make sure that their implementation is solid not merely "compatible-ish". I'd rather optimize for them, rather than the beginners. I'd rather make it easy for them to write correct implementations. I'd rather jettison the "fault tolerant enough that compatible-ish is ok" design of HTTP/1.1 that makes their life so difficult.
I think you made the point for me. TCP, TLS, and DNS (with the exception of OpenDNS a good 20 years later) see no innovation or hacking from startups. Compare to plain text protocols like HTTP.
I'd like to be able to use pipelining without having to de-chunk. That is, thanks to the the HTTP/1.1 protocol I have never found a server that accepts pipelined requests and delivers unchunked output. Is there a reason they must be linked together? Maybe you could compare this to how SPDY requires header compression; you can't get the other features without accepting the compression feature... the single feature which was the source of the security problems.
In sum, why can't we uncouple features that each may have merit on their own?
Optional features tend to be broken in practice. So HTTP/2 is trying to have far fewer of them so that implementations will be more robust.
Chunked requests and pipelines are good examples. They are rarely used but absolutely supported by the spec. But because they are rarely used they break a lot in practice and are not realistically deployable on Internet scale.
I wonder why no one has defined a multi-part message format. The server would deliver a single file, which would start with the HTML and be followed by images and other assets. This approach should play nice with all the proxies (which would see a single octet stream), and, since the pipelining multiplexes everything on a single connection anyway, deliver similar performance.
I understand that no one wants to define a new format, but I don't see how it is more difficult than defining a new protocol.
While intriguing, this suggestion has a number of issues. For one, it implies coalescing a number of resources into a single resource named by a single URL. This means that all resources would have to share the same caching properties. Since it's generally desirable to keep the main document (the HTML) uncacheable to allow site updates, this would imply eliminating the vast majority of web caching, which sounds undesirable.
I may be mistaken, but since everything in SPDY happens over a secure connection, isn't caching already broken? It seams to me that any approach to combining resources to minimize round-tripping will involve a trade-off against the granularity of caching properties.
I think the source of the confusion is that you are conflating sharing of a [SPDY] connection with sharing of a resource identifier (a URI/URL). This is a misunderstanding. SPDY multiplexes multiple streams over a single connection (or more accurately, a session). Each stream is used in the HTTP layering case to correspond to a request/response pair for fetching a resource at a URL. So, even though a single connection is shared, different resources at different URLs can be simultaneously requested over the same SPDY connection.
In short, SPDY does not imply combining resources. Application level combining of resources is a common hack to work around lack of parallelization at the HTTP/1 protocol level, but as noted, it has deficiencies.
I'm aware of the distinction. However, part of the goal of SPDY is to avoid round-trip by pre-emptively sending resources. So the question still remains, why not use some type of archive format to send the HTML along with the images and other assets that would have been pushed down the pipeline? Clients could negotiate for the bundle using Content-accept, and proxies would not be broken.
It seems to me, it wouldn't be that hard to make up a header that says, "Hey, you're GETting '/'. If so you'd probably also like to GET …" Then you send a list of which of those URLs you want (while the HTML for '/' is still being sent), then it sends the rest of the files as one big old MIME blob.
Then again, I don't know much about HTTP, so maybe I'm missing something obvious.
Edit: Hmm, just learned about SPDY's server hinting, which is pretty similar to my idea.
Not sufficient. If you look at the SPDY spec you'll see commands for window control, which is necessary in a serious multiplexing protocol. This spec doesn't have it.
What would an existing proxy server (i.e. doesn't understand HMURR) do with a connection that looked like this?