Rocket
Rocket copied to clipboard
Route doesn't match with valid Accept header
Description
With rocket 0.5.0-rc.1, a route defined as:
#[get("/route", format="image/webp")]
-
Does not match when the Accept header is set to
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -
Does not match when the Accept header is set to
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/avif,*/*;q=0.8 -
Does not match when the Accept header is set to
text/html,application/xhtml+xml,application/xml,image/webp;q=0.9,image/avif,image/webp,*/*;q=0.8 -
Does match with the Accept header set to:
image/webp,text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -
Does match with the Accept header set to:
image/webp -
Does match with the Accept header set to:
*/*
To Reproduce
Define a route e.g.
#[get("/route", format="image/webp")]
pub fn the_route() -> Option<NamedFile> {
todo!()
}
Expected Behavior
All of the above values for the accept header should match the route. The first variant is the value that my copy of Firefox sends out. I'm not clear on what preferred means in the Rocket documentation, but I'd assume at the very least that having image/webp anywhere the higher (0.9) q value should match.
My goal is to be able to respond with a webp image if it exists locally and is supported by the user agent.
Currently a route is matched against a preferred media type for the incoming request. So the default Accept header from Chrome is as follows:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
The preferred media type for this header would be text/html according to the logic in Request::preferred.
The RFC however describes the media type matching as follows:
A more elaborate example is
Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c
Verbally, this would be interpreted as "text/html and text/x-c are
the equally preferred media types, but if they do not exist, then
send the text/x-dvi representation, and if that does not exist, send
the text/plain representation".
In stead of matching a single preferred media type from the request, the media types should be tested in order until it finds a match with a route that can serve a media type.
Not a solution really, but was curious what was causing this behaviour.
Yeah, Rocket just isn't doing proper content negotiation and is ignore the q=x parameters.
This is not uncommon though. Tons of web frameworks have poor content negotiation and long ago I wrote infrastructure for a scala stack to do exactly this. IE Especially sent some brain damaged headers.
Yeah, Rocket just isn't doing proper content negotiation and is ignore the q=x parameters.
No, it's not ignoring the quality parameters at all. Please read the documentation for how Rocket makes use of this information.
There isn't a bug here, as Rocket is doing what it documents it does. However, given that at least one person has considered Rocket's behavior a bug, perhaps it's worth reconsidering how Rocket performs format matching. I'm open to an issue that suggests another strategy for content negotiation. But as this issue doesn't represent a bug, I'm closing it out.