Подскажите, почему я не могу дженерик передать в роутер 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 ответов

94 просмотра

Попробуй использовать 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)); так все работает и проблема мне кажется не в описании дженерика а в чем то другом

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

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

Всем привет. Ребята, подскажите, пожалуйста. у ботов есть ограничение на отправку сообщений - 30 сообщений в секунду, эти ограничения накладываются на все сообщения? или на со...
Artem Stormageddon
4
Блин, ребята, сори за тупые вопросы. А можно ли как-то открыть вебапку по нажатию на кнопку в меню(которое появляется слева, команды)?
Artem Stormageddon
3
Ребята, всем привет. Подскажите, пожалуйста, можно ли как-то через бота понять, что этого бота добавили в группу\канал и выдали ему права администратора?
Artem Stormageddon
9
Привет всем! Почему этот код не срабатывает при добавлении или удалении пользователя из чата? bot.on('chat_member', async (ctx) => { console.log(ctx); }) bot.launch({allo...
Alexander
7
Всем привет. Не понимаю, в чём тут шутка юмора. Убирается только разрешение на send_messages. А send_media_messages остаётся. Как сделать, чтобы оба убирались? await b...
Alexander
2
Есть тут кто занимается разработкой серваков майна? Или знакомые
meow *
3
'frakturBold' => ['𝖆', '𝖇', '𝖈', '𝖉', '𝖊', '𝖋', '𝖌', '𝖍', '𝖎', '𝖏', '𝖐', '𝖑', '𝖒', '𝖓', '𝖔', '𝖕', '𝖖', '𝖗', '𝖘', '𝖙', '𝖚', '𝖛', '𝖜', '𝖝', '𝖞', '𝖟', '𝕬', '𝕭', '𝕮', '𝕯'...
Roma
4
Есть ли лимиты на кол-во вебхук по домену? Стоит в данный момент 900+ ботов и бывает бот перестает отвечать (не приходят вебхуки) 🐒 Помогает только перезапуск
ᅠ [ Кому не ответил, дублируйте ]
11
а что делать если тебя убивают на картах?
Yarik yarik kyda ti lezesh
43
Товарищи, здравствуйте Подскажите, пожалуйста, может кто-нибудь сталкивался с такой задачей Через вебапку можно сканировать qr-код, а есть ли возможность считывать nfc?
Artem Stormageddon
8
Карта сайта