Incorrect parsing of Accept header
Expected Behavior
HTTP Accept headers are permitted to contain accept parameters without a set value. For example:
Accept: application/prs.test;version
When extracting this to a web::Header<http::header::Accept>, the resulting value should be:
Header(Accept([QualityItem { item: "application/prs.test;version", quality: Quality(1000) }]))
The relevant portion of the HTTP/1.1 specification provides the following grammar:
Accept = "Accept" ":"
#( media-range [ accept-params ] )
media-range = ( "*/*"
| ( type "/" "*" )
| ( type "/" subtype )
) *( ";" parameter )
accept-params = ";" "q" "=" qvalue *( accept-extension )
accept-extension = ";" token [ "=" ( token | quoted-string ) ]
The grammar for accept-extension does not require the = character followed by a token/quoted-string in order to be a valid parameter. Similarly, the grammar for a media-range parameter does not specify any such requirement.
Current Behavior
The current behaviour of this results in the following value:
Header(Accept([]))
Possible Solution
The Accept header parser should be updated so as not to require the optional part of accept parameters.
Steps to Reproduce (for bugs)
- Extract a
web::Header<http::header::Accept>value by specifying it as one of the parameters of a service function. - Place
println!("{:?}", accept);within this function. - Send an HTTP request to the server with the following header:
Accept: application/prs.test;version. - Observe that the printed output shows no Accept headers present.
Context
I'm creating an API that is intended to handle different values of a version accept parameter. In the case where the version parameter is missing or is present without a value set, the API should assume a default value. Additionally, the API may accept other parameters that change the representation of the content being returned to the client.
Your Environment
- Rust Version (I.e, output of
rustc -V):rustc 1.64.0 (a55dd71d5 2022-09-19) - Actix Web Version:
4.2.1
Initial investigation reveals that reliance on mime crate is causing this. Reduced playground
Found this issue by happenstance. It is worth pointing out that, according to that RFC, media type parameters without a value are only supported in extension parameters, declared as accept-ext. Media type parameters as mentioned in the syntax for media-range are declared in the part *( ';' parameter), in which parameter is defined in another part of the document as thus:
The type/subtype MAY be followed by parameters in the form of name=value pairs.
parameter = token "=" ( token / quoted-string )
This syntax requires the = character and either a token or a quoted string to appear, without whitespace between them.
With this, it is understood that application/prs.test;q=1.0;version would be fine, but application/prs.test;version would not. 🤯
Given these discrepancies, it is understandable that RFC 9110 preferred dropping support for extension parameters, and proposes a simpler syntax, which is likely the one adopted by mime.
Accept = #( media-range [ weight ] )
media-range = ( "/" / ( type "/" "*" ) / ( type "/" subtype ) ) parameters
Previous specifications allowed additional extension parameters to appear after the weight parameter. The accept extension grammar (accept-params, accept-ext) has been removed because it had a complicated definition, was not being used in practice, and is more easily deployed through new header fields. Senders using weights SHOULD send "q" last (after all media-range parameters). Recipients SHOULD process any parameter named "q" as weight, regardless of parameter ordering.
Hi! I'm learning Rust and Actix Web. I'd like to try fixing this issue as my first contribution. May I take it?
I'm not a maintainer, but I would rather advise to look for good first issues and avoid this one. If the reasoning in my previous message holds true, then this isn't exactly a bug, but rather a decision to implement a simpler (more compatible) Accept header syntax specification.
entendi o que você falou, por sinal deu um entendimento do que esta acontecendo, vou mudar a ótica na verdade se fosse um bug iria tratar como tal, mais ficou melhor de ver como uma implementar especificação de sintaxe, estou dando minha parcela de contribuição acho que não dar para perder nada, mais ganhar com um pouco de conhecimento, valeu mesmo!!