rusttraitslifetimerust-rocket

How to write Rocket FromRequest implementation? Getting "lifetimes do not match method in trait"


I have this code to get the access token from the HTTP request header in Rocket:

use rocket::request::FromRequest;
use rocket::{Request, request};
use rocket::outcome::Outcome;
use rocket::http::Status;

struct Token(String);

#[derive(Debug)]
enum ApiTokenError {
    Missing,
    Invalid,
}

impl<'a, 'r> FromRequest<'a> for Token {
    type Error = ApiTokenError;

    fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
        let token = request.headers().get_one("token");
        match token {
            Some(token) => {
                // check validity
                Outcome::Success(Token(token.to_string()))
            }
            None => Outcome::Failure((Status::Unauthorized, ApiTokenError::Missing)),
        }
    }
}

When I compile the project, it shows an error like this:

error[E0195]: lifetime parameters or bounds on method `from_request` do not match the trait declaration
  --> src/token.rs:17:20
   |
17 |     fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
   |                    ^ lifetimes do not match method in trait

Where is the code going wrong and what should I do to fix this problem?


Solution

  • FromRequest is an async trait. You need to attach that marker and make it async. You don't need to constrain the Request's value's lifetime though, so you don't need two lifetime parameters; you can use '_ there:

    #[rocket::async_trait]
    impl<'r> FromRequest<'r> for Token {
        type Error = ApiTokenError;
    
         async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
             ...
         }
    }