My Rust Actix Web application provides multiple routes to the same resource with different content types. The example below works fine with curl localhost:8080/index -H "Accept:text/html but not in the browser (tested with Firefox developer edition), because that sends Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8.
Is there a way to comfortably handle real-world accept headers such as those, including wildcards and priority scores with the "q" attribute, or do I have to implement this logic myself?
use actix_web::{guard, web, App, HttpResponse, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
web::resource("/index")
.route(
web::get()
.guard(guard::Header("Accept", "text/html"))
.to(|| async {
HttpResponse::Ok()
.content_type("text/html")
.body("<html><body>hello html</body></html>")
}),
)
.route(
web::get()
.guard(guard::Header("Accept", "text/plain"))
.to(|| async {
HttpResponse::Ok()
.content_type("text/plain")
.body("hello text")
}),
),
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
To clarify the expected behaviour:
- the application defines multiple routes with contents C1...Cn with content types T1...Tn in order of preference
- the client (e.g. web browser) sends a get request
- if there is no accept header in the get request, return C1 with content type T1
- if there is an accept header but there is no matching content type including wildcards, return an error response
- if there are multiple matching content types, return the one with the highest q score, assume 1 if not given
- if there are multiple matching content types with the same highest q score, return the one with the lowest index (highest preference by the application)
I could implement this logic myself but given that this seems to be a common case, I was wondering if there is some established method in place that already handles this (or a similar) use case with Actix Web.
I guess you have to write your own guard, but you don't have to parse the header yourself. https://docs.rs/actix-web/latest/actix_web/guard/struct.GuardContext.html#method.header