-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Fix setting content-length: 0
for HEAD responses with compression middleware
#755
Conversation
#753 will fix things properly
I don't think I really understand what went wrong here. |
I understand that its unclear, honestly it wasn't clear to me either. I've done some more digging and think I understand whats going on now: If you have a router like this: Router::new()
.route("/", get(|| async { "Hello, World!" }))
.layer(CompressionLayer::new().compress_when(SizeAbove::new(0))) run it with hyper and send it
I think the most correct thing is to omit the content-length since if the request is issued again with Phew that was a lot 😅 Hopefully it makes sense. |
I see two bugs there:
|
The compression middleware was configured with
Hyper does the right thing afaik. Hyper calls |
If you send a HEAD request the response is
with no body. Before this patch this response would have With this patch the response to
This is unchanged by this patch So
|
content-length
for chunked
responsescontent-length: 0
for HEAD responses with compression middleware
But |
Can you think of other reasonable middlewares / overall setups that would cause the same issue? |
That's true. I think that's a bug in the implementation. The docs says "above a certain size" so I don't think it's a breaking change to fix.
|
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 not really convinced axum is currently doing anything wrong, but clearly this is a way of solving #747 so if you want to go with it, I don't wanna block that.
Fixes #747
The bug was that applying a middleware to a method router would cause the response to pass through a
RouteFuture
twice and we'd set thecontent-length
and strip the response body twice. That happened becauseRouter::layer
wrapped things in aRoute
then calledMethodRoute::route
which also applied aRoute
.Solved it by having
RouteFuture::poll
set a response extension and not alter the response if that is present. Its a little unfortunate to add more overhead here but couldn't think of another solution sinceRouter
andMethodRouter
need to be correct and make sense on their own, and needs to support general services that might not handleHEAD
requests correctly.I also removed
RouterFuture
soRouter
's response is nowRouteFuture<RequestBody, Infallible>
. The additional indirection ofRouterFuture
hasn't proven to be useful so I think its safe to remove.