Подскажите, почему я не могу дженерик передать в роутер axum? Получается

если я явно укажу тип через турбофиш то все компилируется и axum принимает хендлер например
pub fn routes() -> Router {
Router::new().route("/", get(data_all_handler::<ApiDataBase<Language>>))
}
Но если превратить функцию в генеративную data_default_routes то аксум не хочет принимать на этапе компиляции.

pub async fn data_all_handler<T>(Extension(db): Extension<T>) -> Json<DataAllResponse<T::Item>>
where
T: AllDB,
T::Item: ApiItem,
{
let res = db.all().await;
Json::from(res.map_err(|e| e.to_string()))
}

pub fn data_default_routes<T>() -> Router
where
T: AllDB,
T::Item: ApiItem,
{
Router::new().route("/", get(data_all_handler::<T>))
}
Получаю следующую ошибку:
error[E0277]: the trait bound `fn(Extension<T>) -> impl Future<Output = Json<Result<Vec<<T as AllDB>::Item>, std::string::String>>> {data_all_handler::<T>}: Handler<_, _, _>` is not satisfied
--> src/web/api/crud_handlers.rs:34:34
|
34 | Router::new().route("/", get(data_all_handler::<T>))
| --- ^^^^^^^^^^^^^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(Extension<T>) -> impl Future<Output = Json<Result<Vec<<T as AllDB>::Item>, std::string::String>>> {data_all_handler::<T>}`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Handler<T, S, B>`:
<Layered<L, H, T, S, B, B2> as Handler<T, S, B2>>
<MethodRouter<S, B> as Handler<(), S, B>>
note: required by a bound in `axum::routing::get`
--> /home/dima/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.6.18/src/routing/method_routing.rs:403:1
|
403 | top_level_handler_fn!(get, GET);
| ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
| | |
| | required by a bound in this function
| required by this bound in `get`
= note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

19 ответов

54 просмотра

Попробуй использовать debug_handler из axum_macros для хендлера

Дмитрий-Бондаренко Автор вопроса
Huterok
Попробуй использовать debug_handler из axum_macros...

debug_handler не поддерживает дженерики

Дмитрий Бондаренко
debug_handler не поддерживает дженерики

Жалко код не рабочий. Ну да ладно. Похоже что компилятор просто не может вывести нужные зависимости, или вы не указали все необходимые ограничения по трейтам. Может попросить помочь сам компилятор? То есть сделать чтобы data_all_handler возвращал impl Handler

Дмитрий-Бондаренко Автор вопроса
Дмитрий-Бондаренко Автор вопроса
Алишер Галиев
Жалко код не рабочий. Ну да ладно. Похоже что комп...

По ограничениям вроде все есть, сам же data_all_handler работает. Проблема в data_default_routes, ограничения такие же как и в data_all_handler

Дмитрий Бондаренко
По ограничениям вроде все есть, сам же data_all_ha...

Наверное что то все таки не хватает)) вот я и думал как сделать так чтобы компилятор точно сказал чего не хватает. Если при одних данных data_all_handler выдает нужные выходные данные, а при других нет, значит проблема наверное с интерпретацией T::Item. То есть идея сперва работать с вариантом get(data_all_handler::<ApiDataBase<Language>>), попробовав чтобы data_all_handler возвращал impl Handler или impl IntoResponse (вам виднее), все настроить, а уже потом добиться того чтобы data_default_routes работал с дженериком.

Дмитрий-Бондаренко Автор вопроса
Алишер Галиев
Наверное что то все таки не хватает)) вот я и дума...

data_all_handler работает с impl IntoResponse в указанным типом

Попробуйте сделать T и/или DataAllResponse: Serialize.

Дмитрий-Бондаренко Автор вопроса

Вернусь к данному вопросу. Вот сделал простой пример что бы можно было запустить у себя. Кто то может подсказать чего требует компилятор: use axum::handler::Handler; use axum::response::Html; use axum::routing::get; use axum::{Extension, Router}; //use axum_macros::debug_handler; use std::error::Error; use std::net::SocketAddr; use std::str::FromStr; trait Data: Clone { type Item: Into<String>; fn get_item(&self) -> Self::Item; } #[derive(Clone)] struct Container<T>(T) where T: Into<String> + Clone; impl<T> Data for Container<T> where T: Into<String> + Clone, { type Item = T; fn get_item(&self) -> Self::Item { return self.0.clone(); } } //#[debug_handler] doesn't support generic functions async fn handle<T: Data>(Extension(data): Extension<T>) -> Html<String> { let res: String = data.get_item().into(); Html::from(res) } fn router<T: Data>() -> Router { Router::new().route("/", get(handle::<T>)) } #[tokio::main] async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { let data = Container("hello world".to_string()); let router = router::<Container<String>>().layer(Extension(data)); // this work // let router = Router::new() // .route("/", get(handle::<Container<String>>)) // .layer(Extension(data)); let addr = SocketAddr::from_str("127.0.0.1:3001").unwrap(); axum::Server::bind(&addr) .serve(router.into_make_service()) .await .unwrap(); Ok(()) } Я уже что только не перепробовал. Или тут стоит на github в axum писать?

Дмитрий Бондаренко
Вернусь к данному вопросу. Вот сделал простой прим...

У тебя, как я понимаю, дженерик Json не реализует, попробуй

Дмитрий-Бондаренко Автор вопроса
Дмитрий Бондаренко
Json это же не трейт а структура

Ну сейчас пробегусь снова по ошибке, не удобно читать в таком формате

nowaout🦧
Попробуй добавить типаж Handler: T: Data + Handle...

А еще лучше сразу в трейт Data: pub trait Data: Handler + Clone + Send + Sync + 'static

Дмитрий-Бондаренко Автор вопроса
nowaout🦧
А еще лучше сразу в трейт Data: pub trait Data: H...

Там проблема мне кажется не в Data трейте а в самом. Так как функция handler работает и компилится. let router = Router::new() .route("/", get(handle::<Container<String>>)) .layer(Extension(data)); так все работает и проблема мне кажется не в описании дженерика а в чем то другом

Похожие вопросы

Обсуждают сегодня

это как-то фиксится?
Shen
4
А у тебя есть информация сколько сейчас использует твой бот?
Artem Stormageddon
4
Привет всем, как я могу парсить из одного и отправлять в другой канал group media?
Kokni
2
if (user?.choseType === 'oneDay') { await ctx.reply( 'Добро пожаловать в команду «Магнита»! Правда, на один день ☺️ ', ); await ctx.s...
Kokni
1
Сonst magicTgHTML = (text, entities) => { let processedText = text; let offsetShift = 0; entities.forEach(entity => { const { offset, length, type, url, ...
Андрей
1
всем салют сегодня утро заметил что бот не может отправлять фотки по url. ручками в браузере ссылка норм открывает фотки. падает ошибка 'Bad Request: failed to send message ...
Vasya Ivanov
9
а есть какая нить ссылка для быстрого открытия меню со старсами? типа tg://stars
Андрей
6
Всем привет, может не теме чата пишу, но все же. Много ли тех кто с графиками в js работал? Нужно изобразить такой график, на одной временной шкале указать несколько временн...
Степан Губин
2
а что делать если тебя убивают на картах?
Yarik yarik kyda ti lezesh
43
https://t.me/iDubTG/827 это для владельцев каналов?
Андрей
4
Карта сайта