Middleware для извлечения значения 'data' из запроса (rust)

мне на api должны приходить запросы в виде { "data":{ ... } }. мне постоянно надо доставать всю необходимую информацию из data. как мне сделать до того момента, как тело запроса пойдет дальше по маршруту?

#[derive(Debug, Deserialize)]
pub struct ApiData<T> {
    pub data: T,
}

struct ExtractData;

#[rocket::async_trait]
impl<T> Fairing for ExtractData
    where
        T: FromRequest<'static>,
{
    fn info(&self) -> Info {
        Info {
            name: "ExtractData",
            kind: Kind::Request,
        }
    }

    async fn on_request<'a>(&self, req: &'a mut Request<'_>, _: &'a Data<'_>) {
        if let Some(data) = req.guard::<ApiData<T>>().succeeded() {
            req.local_cache(|| data.data);
        } else {
            req.set_abort(Some(Status::BadRequest));
        }
    }
}

#[launch]
async fn rocket() -> _ {
    let db = MongoRepo::init().await;
    rocket::build().manage(db)
        .attach(ExtractData)
        .mount("/api/", routes![get_files_in_directories])
        .mount("/api/usepi/patterns", routes![create_pattern])
        .mount(
            "/api/usepi/patterns/icons",
            FileServer::from(Path::new("./src/icons")),
        )
}

я пытаюсь это реализовать таким способом, но всегда ошибки по типу

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> src/main.rs:54:6
   |
54 | impl<T> Fairing for ExtractData
   |      ^ unconstrained type parameter

не знаю, как сделать правильно, подскажите пожалуйста


Ответы (1 шт):

Автор решения: Exdet
async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {
        if let Some(content_length_str) = req.headers().get_one("Content-Length") {
            if let Ok(content_length) = content_length_str.parse::<usize>() {
                let peek_data_string = String::from_utf8_lossy(data.peek(content_length).await).to_string();
                match serde_json::from_str::<ApiData>(&peek_data_string) {
                    Ok(api_data) => {println!("Deserialized data: {:?}", api_data);}
                    Err(err) => {eprintln!("Error parsing JSON: {:?}", err); }
                }
            } else { eprintln!("Failed to parse Content-Length as usize"); }
        } else { eprintln!("Content-Length header not found"); }
    }
→ Ссылка