Hacker News new | ask | show | jobs
by xeeeeeeeeeeenu 2052 days ago
Sadly, HTTP 103 hints, which provide a much saner way to preload content, are still unimplemented in all major browsers.
3 comments

For people like me who are unfamiliar with the proposal, 103 Early Hints [1] would work like this.

Client request:

  GET / HTTP/1.1
  Host: example.com
Server response:

  HTTP/1.1 103 Early Hints
  Link: </style.css>; rel=preload; as=style
  Link: </script.js>; rel=preload; as=script
  
  HTTP/1.1 200 OK
  Date: Fri, 26 May 2017 10:02:11 GMT
  Content-Length: 1234
  Content-Type: text/html; charset=utf-8
  Link: </style.css>; rel=preload; as=style
  Link: </script.js>; rel=preload; as=script
  
  <!doctype html>
  [... rest of the response body is omitted from the example ...]
[1]: https://tools.ietf.org/html/rfc8297
Do you mean that the same HTTP/1.1 GET request can have two different headers with two different status code?

What's the reported status code of this response in typical libraries? Usually the status code is a single value and not a list.

10x status codes are already used for multipart requests and responses, right? 100 Continue and the like. This is usually handled transparently by your client library.
I'm going to assume many HTTP libraries and ad-hoc implementations expect one HTTP response for one HTTP request (but still support pipelining) and will break if this underlying assumption changes.

In fact, this may even be ratified in the interfaces they provide: think synchronous "give contents of this URL" functions.

That's the most significant criticism of RFC 8297 (the 103 Early Hints response) from my cursory reading of the RFC. It should only be allowed when the client indicates that it can process 1xx responses. All other 1xx responses are like that AFAIK, e.g. 100 Continue is only sent when the client sets the "Expect: 100-continue" header. So a client that doesn't do that doesn't need to care about 100 Continue responses.
The client should send Expect: 103-early-access in order for the server to send it. :(
Yep, two (or more, the spec allows for multiple 103 responses before the "real" response) responses returned from one request.

The one library I threw a test server at didn't respond well. It treated the 103 as the response, and the actual 200 as the body. It was an older library, and the spec suggests using client sniffing to pick which clients to send 103 to. That's kinda when I stopped trying to figure it out, I'm not surprised to learn no one really implements it.

Yes, that's how 100-Continue works and it is widely implemented (but mostly this is hidden by application libraries):

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/100

So at best this saves a couple of bytes until you get to the html header which can link to these resources with preload attributes anyway?
The intent is to allow even earlier preloading than what `Link` headers in the response or `<link>` in the HTML would typically allow. The insight here is that most application servers/webservers get a request and only send the response headers all at once, with the body, once everything is ready. But many times you already know some static resources ahead of time, before you know what response to send back.

For example, if you make a request for `GET /users/id/12345`, you know the user probably needs `style.css` like most do. You put that into a `Link` header in the response. But the browser won't fetch that file until it is told about it. It will only be told about it once it has seen the entire response, because again, the server (probably) sends it all at once, body and headers together, anyway.

But, producing that page in the first place may require running database queries for user info, your template engine to get run for the page body, an external HTTP call to happen in the background for their Gravatar, etc. So all of that has to happen on the server side before style.css can be fetched by the client browser. Even though you (the developer) knew they (the client) probably needed it. Let's say that `GET` request needs 500ms of computation (DB query + API call) before a reply is sent. That means the client has to wait at least 500ms for the server to produce any Link headers -- 500ms before it can fetch style.css. More importantly, it's literally 500ms where the client browser does nothing while it waits, while it could be concurrently downloading other assets, for example.

With Early Hints, when someone issues a `GET /users/id/12345`, the server can immediately reply using an Early Hint and tell the client about style.css first-thing. Then the client can immediately go fetch style.css, without waiting 500ms for the server to produce the body, or the headers, or even anything at all.

One interesting advantage of this is that, like Link headers, but unlike Server Push, early hints can be statically computed at at "application build time." You just need a mapping of URIs to URIs, like preload. So you can imagine for example your Django Middleware or Rails App or NodeJS Thing-Doer might have a step where it calculate asset dependencies for your frontend, and has a middleware layer that automatically issues 103 Early Hints for statically known page assets. And unlike Push, Early Hints are client-controlled. A big problem with Push is that it has no knowledge of the client-side cache, so it can push assets unnecessarily and cause slowdown. Early hints has no such drawback; the client has complete knowledge of its cache state and can make the correct decision.

I'm not sure if i see much benefit over just having a header on the 200 response. I suppose if it takes a bunch of time to generate the response body, but most of the time where this sort of thing would make a difference you probably already have the response body for the main request cached on the server side.
I guess the advantage is that you can send this before you know the status code of the response? For example if you know what CSS+JS file the client will need but still need to generate the page which may 500, 404 or 302.
And I can't understand why!