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"); }
}