Tokio to Actix-web

Hello
I'm trying to test this example in actix-web but I don't know how to do it.
I have problems with Box<dyn std::error::Error>, in actix-web it gives me an error

use keycloak::{
    types::*,
    {KeycloakAdmin, KeycloakAdminToken},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = std::env::var("KEYCLOAK_ADDR").unwrap_or_else(|_| "http://localhost:9080".into());
    let user = std::env::var("KEYCLOAK_USER").unwrap_or_else(|_| "admin".into());
    let password = std::env::var("KEYCLOAK_PASSWORD").unwrap_or_else(|_| "password".into());
    let client = reqwest::Client::new();
    let admin_token = KeycloakAdminToken::acquire(&url, &user, &password, &client).await?;

    eprintln!("{:?}", admin_token);

    let admin = KeycloakAdmin::new(&url, admin_token, client);

    admin
        .post(RealmRepresentation {
            realm: Some("test".into()),
            ..Default::default()
        })
        .await?;

    admin
        .realm_users_post(
            "test",
            UserRepresentation {
                username: Some("user".into()),
                ..Default::default()
            },
        )
        .await?;

    let users = admin
        .realm_users_get(
            "test", None, None, None, None, None, None, None, None, None, None, None, None, None,
            None,
        )
        .await?;

    eprintln!("{:?}", users);

    let id = users
        .iter()
        .find(|u| u.username == Some("user".into()))
        .unwrap()
        .id
        .as_ref()
        .unwrap()
        .to_string();

    admin
        .realm_users_with_id_delete("test", id.as_str())
        .await?;

    admin.realm_delete("test").await?;

    Ok(())
}

how would it be?

use keycloak::{
    types::*,
    {KeycloakAdmin, KeycloakAdminToken},
};
use std::error::Error;



#[actix_web::main]
async fn main() -> std::io::Result<()> {
    
    HttpServer::new(|| App::new().route("/ping", web::get().to(ping)))
        .bind(("127.0.0.1", 4141))?
        .run()
        .await
}

It's not very clear what your exact problem is. Could you please provide the error message you receive?

Only guesswork, but would not returning Result<_, _> from main be an option? Instead of using the ? operator, you'd have to call .unwrap().

If you want to return Result<_, Box<dyn std::error::Error> from a route in actix-web, try adding the + 'static bound like this: Result<_, Box<dyn std::error::Error + 'static>. Your error needs to implement ResponseError if you want to return it from a route.

When I try this.

#[actix_web::main]
async fn main() -> std::io::Result<()> {

    let url = "http://192.168.10.8/auth";
    let user = "admin";
    let password = "123456";
    let client = reqwest::Client::new();

    let admin_token = KeycloakAdminToken::acquire(&url, &user, &password, &client).await?;
    

    HttpServer::new(|| App::new().route("/ping", web::get().to(ping)))
        .bind(("127.0.0.1", 4141))?
        .run()
        .await
}

This is the error message it shows

error[E0277]: `?` couldn't convert the error to `std::io::Error`
  --> app/src/main.rs:56:89
   |
56 |     let admin_token = KeycloakAdminToken::acquire(&url, &user, &password, &client).await?;
   |                                                                                         ^ the trait `std::convert::From<KeycloakError>` is not implemented for `std::io::Error`
   |

That is because KeycloakAdminToken::acquire does not return a Result<_, std::io::Error> but Result<_, KeycloakError>. There is no implementation of From<KeycloakError> for std::io::Error, which is why using ? for error propagation won't work. Try replacing ? with .unwrap():

let admin_token = KeycloakAdminToken::acquire(&url, &user, &password, &client).await.unwrap();

As a general note, Box<dyn Error + Send + Sync> should be preferred over Box<dyn Error>.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.