rustrust-actix

Is there simpler method to get the string value of an Actix-Web HTTP header?


Is this is the only possibility to get the content-type header from an Actix-Web request? This has to check if the header is available or if to_str failed...

let req: actix_web::HttpRequest;

let content_type: &str = req
    .request()
    .headers()
    .get(actix_web::http::header::CONTENT_TYPE)
    .unwrap()
    .to_str()
    .unwrap();

Solution

  • Yes, that is the "only" possibility, but it's like that because:

    1. The header may not exist, headers().get(key) returns Option.
    2. The header may have non-ASCII chars, and HeaderValue::to_str might fail.

    actix-web lets you handle those errors individually.

    To simplify, you could make a helper function that does not differentiate between the two errors:

    fn get_content_type<'a>(req: &'a HttpRequest) -> Option<&'a str> {
        req.headers().get("content-type")?.to_str().ok()
    }
    

    Full example:

    use actix_web::{web, App, HttpRequest, HttpServer, Responder};
    
    fn main() {
        HttpServer::new(|| App::new().route("/", web::to(handler)))
            .bind("127.0.0.1:8000")
            .expect("Cannot bind to port 8000")
            .run()
            .expect("Unable to run server");
    }
    
    fn handler(req: HttpRequest) -> impl Responder {
        if let Some(content_type) = get_content_type(&req) {
            format!("Got content-type = '{}'", content_type)
        } else {
            "No content-type header.".to_owned()
        }
    }
    
    fn get_content_type<'a>(req: &'a HttpRequest) -> Option<&'a str> {
        req.headers().get("content-type")?.to_str().ok()
    }
    

    Which will give you the results:

    $ curl localhost:8000
    No content-type header.⏎
    $ curl localhost:8000 -H 'content-type: application/json'
    Got content-type = 'application/json'⏎
    $ curl localhost:8000 -H 'content-type: 💩'
    No content-type header.⏎
    

    By the way, you may be interested in guards:

    web::route()
        .guard(guard::Get())
        .guard(guard::Header("content-type", "text/plain"))
        .to(handler)