Rocket icon indicating copy to clipboard operation
Rocket copied to clipboard

Route doesn't match with valid Accept header

Open inferiorhumanorgans opened this issue 4 years ago • 3 comments

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.

inferiorhumanorgans avatar Oct 22 '21 07:10 inferiorhumanorgans

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.

tiaanl avatar Nov 11 '21 12:11 tiaanl

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.

DanielJoyce avatar May 03 '22 23:05 DanielJoyce

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.

SergioBenitez avatar May 04 '22 04:05 SergioBenitez

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.

SergioBenitez avatar Apr 11 '23 16:04 SergioBenitez