You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I would like to propose (and implement) a module that provides a public API to parse and evaluate HTTP content negotiation headers. Initially, it should support encoding negotiation (Accept-Encoding header) and language negotiation (Accept-Language).
Motivation
Various existing (Rust and non-Rust) content negotiation implementations I inspected are incomplete, or get details wrong, or are not easily accessible as a public API. It would be valuable to have a RFC 7231-compliant implementation in Tower HTTP.
Tower HTTP's existing content encoding negotiation implementation is currently not a public API and therefore limited to on-the-fly encoding and delivery of pre-encoded files. It would be helpful if it could be used for other cases, e.g. static data compiled into the server executable. Such a self-contained executable could run on an embedded device without a filesystem.
Language negotiation would be a new feature in Tower HTTP. If the “negotiation part” (parsing and evaluation of qvalues, comparison with available options, selection of the right preference) is implemented in a generic way, it would be easy to implement both encoding and language negotiation on top of that.
Proposal
I propose the public API to look like this:
The API user provides a list of available options (encodings or languages). The list is sorted according to server preference.
The module parses and evaluates the Accept-Encoding or Accept-Language header.
If there is a unique option preferred by the client according to the header, it is returned.
If there are multiple options that the client prefers equally, the option among those that the server prefers most is returned.
If none of the options is acceptable to the client, None is returned.
The RFC does not specify what option is chosen if the client prefers multiple options equally. It is possible to return an arbitrary one, or the one that is first mentioned in the header, or the one that the server prefers. IMHO, the latter makes the most sense. The server may have information that the client cannot know. E.g., the server knows which compressed file is the smallest, or which language translation is the most complete.
What happens if no option is acceptable depends on the negotiation type. For encoding negotiation, the request should be rejected with a 406 Not Acceptable response. For language negotiation, the RFC recommends disregarding the Accept-Language header, although it also allows a 406 Not Acceptable response.
I propose to generalize Tower HTTP's content encoding negotiation implementation and to simultaneously fix its knows issues (#215). The existing content encoding negotiation usages would then be adapted to the generalized implementation.
Alternatives
I considered fixing #215 first. However, IMHO the remaining issues are easier to fix in a generalized implementation.
Please let me know what you think!
The text was updated successfully, but these errors were encountered:
Is this something that could be built in a separate crate, in a general purpose/generic way, and then integrated into tower-http through a middleware?
tower-http's API surface is already quite large and any breaking change in a middleware is a breaking change to all the others. So I think it's worth trying to keep the API small.
I also don't know that we have the bandwidth to take on maintaining something like this, but that depends on the scope of course.
Feature Request
I would like to propose (and implement) a module that provides a public API to parse and evaluate HTTP content negotiation headers. Initially, it should support encoding negotiation (
Accept-Encoding
header) and language negotiation (Accept-Language
).Motivation
Various existing (Rust and non-Rust) content negotiation implementations I inspected are incomplete, or get details wrong, or are not easily accessible as a public API. It would be valuable to have a RFC 7231-compliant implementation in Tower HTTP.
Tower HTTP's existing content encoding negotiation implementation is currently not a public API and therefore limited to on-the-fly encoding and delivery of pre-encoded files. It would be helpful if it could be used for other cases, e.g. static data compiled into the server executable. Such a self-contained executable could run on an embedded device without a filesystem.
Language negotiation would be a new feature in Tower HTTP. If the “negotiation part” (parsing and evaluation of qvalues, comparison with available options, selection of the right preference) is implemented in a generic way, it would be easy to implement both encoding and language negotiation on top of that.
Proposal
I propose the public API to look like this:
Accept-Encoding
orAccept-Language
header.None
is returned.The RFC does not specify what option is chosen if the client prefers multiple options equally. It is possible to return an arbitrary one, or the one that is first mentioned in the header, or the one that the server prefers. IMHO, the latter makes the most sense. The server may have information that the client cannot know. E.g., the server knows which compressed file is the smallest, or which language translation is the most complete.
What happens if no option is acceptable depends on the negotiation type. For encoding negotiation, the request should be rejected with a
406 Not Acceptable
response. For language negotiation, the RFC recommends disregarding theAccept-Language
header, although it also allows a406 Not Acceptable
response.I propose to generalize Tower HTTP's content encoding negotiation implementation and to simultaneously fix its knows issues (#215). The existing content encoding negotiation usages would then be adapted to the generalized implementation.
Alternatives
I considered fixing #215 first. However, IMHO the remaining issues are easier to fix in a generalized implementation.
Please let me know what you think!
The text was updated successfully, but these errors were encountered: