New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add rack.early_hints to SPEC #1831
base: main
Are you sure you want to change the base?
Conversation
I want to find a way to move forward here but I have a hard time accepting this interface because even if not initially apparent, it does introduce a lot of downstream complexity which I'm not sure we are prepared to deal with. Just to confirm, the RFC is still marked as experimental right? https://httpwg.org/specs/rfc8297.html When I look at a feature like this, I have to consider how it fits into Early hints are effectively multiple responses per request which is very uncommon in normal HTTP (at least in my assumptions about what typical developers think about HTTP). Sure, you can implement it as a hook on the incoming request (as proposed), but it's actually a feature of the response. Architecturally this is a huge problem, since Early hints make this representation significantly more complex. A practical example of this is how Falcon works internally when handling virtual hosts. Falcon has a front end proxy which talks SSL + HTTP/1 or HTTP/2. Internally, it talks to the application server using plain text HTTP/2 via a unix domain socket. If the application server replies with a 1xx provisional response, the proxy layer has to understand this and correctly send it to the client. This requires early hints / provisional responses to become a first class concept within the semantic request/response models, and any code that deals with transiting requests/responses needs to be aware of those new interfaces. This is the complexity which I'm not comfortable with, without seeing significant performance advantages. The same logic applies to push promises which is why I wouldn't mind removing them simply because I'm not sure the additional complexity yields any practical impact. Therefore, the bar for supporting this functionality should exceed the additional complexity both at the semantic level (how we model requests and responses) and the user level (how users are expected to generate and consume these extra early hints). That bar for me is pretty high, and I'm still not sure the performance advantage. Does the cost of the complexity yield a significant performance advantage? By standardising this in Rack, we are sending a message: this is an important part of the HTTP semantic model that we allow you to use. However, the net result might be a fair amount of disappointment as people find the performance is less advantageous than expected. And the net result is a huge amount of technical complexity we now have to carry forward, both on the server side and client side. I'm happy to experiment with this further, but I hesitate to standardise it without evidence that it provides a significant advantage, especially given that there is a more general interface (provisional response) which fully captures the actual semantic of HTTP. I'd be more willing to consider the provisional response interface, but even then I'd like to see the performance advantage. As existing servers already support it, I don't see why it can't be tested in the real world with real data collection to show it's impact. Standardisation in rack does not appear to me to be a barrier to this testing. |
Just for my own edification I was reading https://blog.cloudflare.com/early-hints/ and felt it summarised some key issues nicely:
It also outlines some steps they have tried to address those problems. |
Do any browsers support this on HTTP/1? It looks like this isn't supported on HTTP/1 by most common browsers? |
First, this is purely an optional part of Rack, so servers do not have to implement it if they don't want to accept the complexity. From looking at the Unicorn and Puma implementation, the complexity required is not trivial, but it's not large either.
This should be a decision made by each web server. Servers that don't think the performance advantage outweigh the complexity disadvantages should not implement it. Again, this is a purely optional part of the spec, being formally standardized as it is already the de facto standard. I get for Falcon/async-http, supporting early hints may not be worth it. I think it's fine not to support it. After all, it is optional, not required, by design.
No. By standardizing this as an optional part of rack, we are sending a message that if you want to use this feature as a server or as a framework, this is the interface you use. This is no recommendation that you should use it, merely a specification of the interface to use it for the server/framework to use.
I don't understand this logic. Everything you seem to be against with early hints would also apply to provisional responses. While there are use cases for early hints (even if you don't think they are that useful), I have not seen a single use case of provisional responses other than for early hints. If in some theoretical future, there was actually a use for provisional responses, we could implement
Chrome doesn't support it on HTTP 1.1: https://chromium.googlesource.com/chromium/src/+/master/docs/early-hints.md |
I'm only slightly more positive towards provisional responses, but at least it's the actual semantic model that's exposed at the protocol level. I don't agree with your YAGNI assessment. Standardising it in Rack is we make it a defacto standard which can then make it harder to later implement better interfaces. Frankly, if we want to provide an interface for informing browsers that they should download specific files, I don't think this is a good one. I think it would make more sense to write it like this:
With such an interface, mapping to early hints, push promises or anything else becomes much more trivial. If you are arguing that a specific interface here makes sense, I don't think a generic list of headers make sense. |
Can you provide a single use case for a provisional response other than early hints? If not, YAGNI (not yet, at least).
rack.early_hints is already a de facto standard, because that's what web servers implement and what web frameworks use. Us standardizing rack.early_hints takes it from a de facto standard to a de jure standard.
I'm making the same argument made by @tenderlove at #1701 (comment):
IMO, neither the provisional response interface nor the modified interface in your comment is better enough that we should ask all existing implementations to change their code. |
"100 Continue" |
That's a status code, not a use case. Can you explain how/why you would use provisional responses in an application with status code 100? |
100 continue can be used to inform the client that authorisation header was successful and they can continue to upload the request body. |
I'll give you that that is at least a theoretical use case, though I'm not sure there is any software that actually does that. In any case, I've said my piece. If the fact that existing servers and frameworks already use rack.early_hints is not sufficient evidence this should be merged, it doesn't seem productive to continue to attempt to persuade. @tenderlove @rafaelfranca @matthewd I'd appreciate if one of you could give your opinion on whether or not this should be merged. |
I've read about it being used to prevent large uploads beings sent before auth is performed, e.g. https://support.airship.com/hc/en-us/articles/213492003--Expect-100-Continue-Issues-and-Risks https://evertpot.com/http/100-continue/ also has a great overview of different use cases for 100 continue, 102 processing and so on. So not just theoretical. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with @jeremyevans and @tenderlove on this. If most web frameworks and most popular ruby servers already implement this feature it is already a de-factor standard of rack.
I don't see we removing this feature with push back from the frameworks. I also don't see we changing this feature without taking in consideration the actual usage.
In my opinion we should add to the spec as an optional part of Rack.
After thinking about this, I'm ultimately fine with it, but I still believe it's a mistake to introduce a specific interface when a more general one exists (and has valid use cases). It sets the bar incorrectly for framework and middleware authors IMHO which creates long term technical debt; and there is also a performance cost to servers setting additional I'd personally prefer we implement |
The chicken and egg problem has been partly solved, as Chrome 103 supports Early Hints. @tenderlove what are your thoughts on this issue? |
"Supports" may be a bit too strong.
They are testing a prototype and it can be removed in a future release. I've seen this kind of thing before and more likely than not it will end up being removed. As I said earlier my position is we should support a generic interface like |
@ioquatix I'm not sure if you are aware, but it looks like your quote is from February 2021, when they were at the testing/evaluation stage (https://groups.google.com/a/chromium.org/g/blink-dev/c/DAgWIczGtG0/m/gSXvjYn-AwAJ). Your quote does not reflect the current status in Chrome. The release announcement for Chrome 103 (https://developer.chrome.com/blog/new-in-chrome-103/) has Early Hints as the most important new feature in the release. It's not beyond the realm of possibility that they will remove it, but there is no language indicating they are at the testing/evaluating stage. Unless you have a better current source, it appears Early Hints is fully supported for production use as of Chrome 103. |
I was referring to this page: https://chromestatus.com/feature/5207422375297024 |
By the way, my position doesn't change much, but I'm really excited by this feature. I still think My reasoning is:
I'm not against anyone using early hints, I personally think it's an interesting idea - but there are a ton of challenges with provisional responses because they essentially mean that one HTTP request has multiple responses and that's unexpected for 99% of use cases. The counter-point is simply being able to send link headers in the initial headers, and streaming the response body, which is effectively the same in terms of what kind of performance you should be able to get by hinting the browser what resources to load. Another counter point is HTTP/2 server push which is essentially dead. It's very very similar to early hints, except that instead of being browser initiated, the server initates the stream and pushes the resources it thinks the browser will need. This would be one data point as to why I'm not sure if |
Considering the language is the same as the February 2021 blog post, it is likely stale. This was tested in Origin trails from Chrome 94 to 102. It seems unlikely to me that after testing it in 9 versions, and deciding it is good enough to enable by default, that they would remove it. It's not just servers that support Anyway, seems pointless to rehash the same discussion that we had earlier in the issue. My point in updating this issue was to add new information not previously discussed (chicken and egg problem solved, now fully supported in Chrome 103!), not to have the same discussion again. |
0915672
to
478b19b
Compare
As @tenderlove, @rafaelfranca, and I are in favor of this, I plan on merging this in a couple days. I think this and |
Are you also happy with adding a spec for an optional |
Not at present. |
I want to get input from server authors before this is merged. @FooBarWidget @nateberkopec I went looking through the original discussion and @tenderlove seemed to be in agreement with adding the status code: #1692 (comment) however maybe his position is updated/changed. @tenderlove can we get your input on this? If I ever decided to implement something to this effect in As I've already explained, it doesn't make sense to support both interfaces when one is a strict superset of the other, so we should be careful about what we introduce and what that communicates to our users. It would be nice to support |
One difference between Let's examine the links you posted previously in favor of your argument:
Regarding 100:
Regarding 102:
|
Will apply to all 1xx status codes. I was interested in this so I just whipped up a fake 103 server: https://github.com/socketry/protocol-http1/blob/main/examples/early-hints/server.rb At least, libcurl and |
8b4d653
to
a4c5b6d
Compare
@tenderlove I've rebased this against current master. Can you approve (or request changes)? This is the last blocker for Rack 3, AFAIK. |
This is already de facto spec as both Unicorn and Puma
implement it. The changes to SPEC are compatible with
both implementations.
Fixes #1692
Fixes #1695
Co-authored-by: Jeremy Evans code@jeremyevans.net