-
Notifications
You must be signed in to change notification settings - Fork 10.2k
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
HTTP/1.1 Allow Response Trailer Headers #4627
Comments
Would need design |
I don't think this is super important. If you really want this, I think you should be willing to manually chunk your response which you can do if you explicitly set |
@halter73 how do you send response trailing headers using existing APIs? |
@madelson I'm not aware of any way to do this using HttpClient APIs. You would probably have to build something on raw sockets. |
Proposal: Request and response trailer headers belong in their own collections. These should get there own features. These features should also have a HasStarted type flag indicating if the trailers have been started or finished yet. The response trailers feature may even have a Flush method to end the body and send the trailers immediately. Today kestrel puts request trailers into the normal request headers collection, but this may cause conflicts or concurrent modification errors. |
I hit a desire for these today, in MiniProfiler. There's now a But There is a minor question open here, where in the initial headers collection needs knowledge a trailer exists. I'm not sure the best API for that - perhaps there's just a method (called before headers are sent) that takes a header name, which registers them for the |
Yeah, you'd have to signal that you'll set a trailer before the response is started. Otherwise the response would be invalid. If you set trailers early enough that could be done automatically, but this wouldn't work for things like |
Just throwing out ideas - perhaps something like this: context.Response.RegisterTrailerHeader("Server-Timing"); |
What if the body ends up not being chunked? |
How about this? |
Why not just |
Does it write the trailing header? |
There are 2 issues you have a header you need to write... that has which headers are in the trailer and write the trailing headers themselves. This middleware takes a call back to write the header content later. When you register it indeed populates the response.headers ["Trailers"] for you but it also takes over chunking for you and then calls your call back after writing the zero chunk but before closing doing the last /r/n Why they didn't call them footers instead of trailing footers I guess will remain one of life's great mysteries |
@Drawaes much appreciated - I agree that's a tenable solution (some perf increases to be had there), but not something I'd consider doing in a library...that's quite dramatic on the impact to an application to change out in middleware of a profiling library (IMO). I think that yes we can do this, but without core support, it'd be ethically questionable for me to do that ;) |
Ethics, meh. Yeah it's a POC not prod ready code, for instance it doesn't handle the case where no body should be sent. But it's tenable, As for the library question if it's a feature people enable or disable then it's up to them. As for the perf if it was optimised, should be able to be pretty much a single method dispatch the rest of the code is very similar to what the chunker is doing now it's just been replaced with a custom one. As with all things direct framework support would be better. |
@Drawaes My point is: if MiniProfiler changed an app's transfer encoding, that'd be really bad and completely unexpected. Framework support is essential here, for several reasons:
There are just too many things to break here, and I'm very adamant this is outside the purview of a profiler. We'd need framework support for the case where the response isn't chunked, and the header behave as a normal header as well. Since all the pieces need to work together here, I think it being core functionality that contains this logic that we call instead of provide is critical, in this specific case. |
I agree... of course if 10 apps want to add trailers they can all use the same middleware ;) Ssl for instance isn't baked in nor is connection logging so it could be a connection filter ( or adapter) in the future. |
What is interesting.... HttpClient works (read ignores) these on windows, but on ubuntu crashes with System.Net.Http.HttpRequestException : Error while copying content to a stream. |
Update on motivation for support here - Chrome is landing support for server timings in M65: https://blog.chromium.org/2018/02/chrome-65-beta-css-paint-api-and.html |
Same issue here. You need to specify which trailers you want before you start sending the response. I'd expect to register the trailers i want when i initialise my code in the request pipeline, specifying i want to send certain headers. This has to be done before the body starts being sent, and forces chunked encoding. After the entity body is sent, i get a OnSendingTrailerHeaders() notification, and the fx puts whatever registered trailers were specified in the trailer part. This would allow us to use Server-Timings more efficiently than today, where I basically can't measure anything from the moment i start writing stuff when the response is buffered. Currently openrasta doesn't try and force one mode over the other, and relies on whatever is given to it by the hosting environment (as owin, kestrel, httplistener and systemweb have different behaviours there, and we still support multi hosting). As it stands, if the response coding part of the pipeline has metrics, we can't put those in the header, unless we magically unable buffering, which has memory implications. |
Design notes: This applies to both HTTP/1.1 and HTTP/2, but is more relevant for HTTP/2. Detecting trailers support?
Declaring trailers:
Adding trailers:
Feature: IHttpResponseTrailersFeature
Cross server notes:
|
I would let apps do that themselves if they want.
I agree that we should discard and log.
If the DeclareTrailer API is used, I like being strict. If the Trailers header is manually added, I would give maximum leeway to the app. So throw when DeclareTrailer is called if another header like Content-Length that would disable chunking has already been set. Similarly, throw when setting Content-Length if it's done after calling DeclareTrailer. Some more questions:
I don't have a recommendation yet, but TrailersEnabled isn't very self-explanatory. It being null before the response starts isn't very intuitive. I think I prefer it being true for HTTP/1.1 requests until some header is set that would prevent chunking. Based on the name alone, I would expect this to communicate client support for trailers instead of verifying the the response was set up correctly, so maybe we can come up with a better name too. |
Throwing from DeclareTrailer or ContentLength seems like a poor user experience, they'll likely be called by independent components (e.g. tracing middleware and StaticFiles). Fixup or discard would be better, but it might have to happen at the server level when preparing the headers to send.
Tracking request trailers in https://github.com/aspnet/KestrelHttpServer/issues/2051.
I think so, it's only a SHOULD. I covered this above as "No strong verification that the items you add were listed in the response Trailers header."
Hmm. A warning seems a bit strong, debug maybe. Trailers can't be un-declared after the headers are sent if something goes wrong.
Yes, but you can't guarantee they'll get sent.
I would expect Trailers to commonly be declared before Content-Length, henice the discard or fixup question above.
Yes, by the server at the end of the request. It's the new WriteSuffix.
After. That's a final Dispose that is not guaranteed any access to the HttpContext.
Agreed it needs some work. Having it change from true to false seems like it would reduce its usefulness. |
I have an HTTP/2 prototype over at aspnet/KestrelHttpServer@96b0c85. I realized that the simplest design is to only provide an IHeadersDictionary and send it at the end of the response stream where we would normally send the terminator. While this does have the added latency of forcing you to wait until the app func unwinds, that's no worse than the current chunked terminator behavior and allows middleware to reliably add trailers.
|
This has been completed for HTTP/2 in 2.2.0-preview3. I'm updating this issue to clarify that it now only tracks HTTP/1.1. |
Is there any update in the plans for this? I'm just curious if |
This is done |
Now (shortly?) reading request header trailers #619; ability to add them to chunked encoding responses?
Currently supported by(Misleading)System.Web
Don't think browsers pay attention to them; but some discussion on whatwg/fetch#34 as to their importance for CDNs etc; and whether to include them in the fetchapi
The text was updated successfully, but these errors were encountered: