[Solved] Noob in web dev, struggling with warp

#1

Hi!

I’m trying to write my first web server and I’m struggling with warp.

fn main() {
    // PUT /user/
    let create_user = path!("user" / String / String).map(|u: String, p: String| {
        match user::create_user(u.as_str(), p.as_str()) {
            Ok(token) => Ok(warp::reply::json(&token)),
            Err(e) => Err(warp::reply::json(&e)),
        }
    });

    let put_routes = warp::put2().and(create_user);

    warp::serve(put_routes).run(([127, 0, 0, 1], 3030));
}

in another module:

pub fn create_user(username: &str, password: &str) -> Result<Token, ServerError> {
  return Ok("".into()); // placeholder
}

I got this error:

error[E0277]: the trait bound `std::result::Result<impl warp::reply::Reply, impl warp::reply::Reply>: warp::reply::sealed::ReplySealed` is not satisfied
  --> src\main.rs:17:5
   |
17 |     warp::serve(put_routes).run(([127, 0, 0, 1], 3030));
   |     ^^^^^^^^^^^ the trait `warp::reply::sealed::ReplySealed` is not implemented for `std::result::Result<impl warp::reply::Reply, impl warp::reply::Reply>`

I think the issue is that I’m trying to return a Result when warp is expecting a Reply. But I tried:

fn main() {
    // PUT /user/
    let create_user = path!("user" / String / String).map(|u: String, p: String| {
        match user::create_user(u.as_str(), p.as_str()) {
            Ok(token) => warp::reply::json(&token),
            Err(e) => warp::reply::json(&e),
        }
    });

    let put_routes = warp::put2().and(create_user);

    warp::serve(put_routes).run(([127, 0, 0, 1], 3030));
}

But still no luck:

error[E0308]: match arms have incompatible types
  --> src\main.rs:9:9
   |
9  | /         match user::create_user(u.as_str(), p.as_str()) {
10 | |             Ok(token) => warp::reply::json(&token),
11 | |             Err(e) => warp::reply::json(&e),
   | |                       --------------------- match arm with an incompatible type
12 | |         }
   | |_________^ expected struct `user::token::Token`, found struct `error::ServerError`
   |
   = note: expected type `impl warp::reply::Reply` (struct `user::token::Token`)
              found type `impl warp::reply::Reply` (struct `error::ServerError`)

Meaning that Reply is a generic.

How can I achieve returning a json version of Token or json version of ServerError according to the result of create_user?

Thanks!

#2

n/m

#3

Thank you for your answer!

These two type are defined like this:

use std::error::Error as StdError;

#[derive(Debug, Serialize)]
pub struct ServerError {
  status: i32,
  msg: String,
}
impl Display for ServerError {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    write!(f, "{}", self.description())
  }
}

impl StdError for ServerError {
  fn description(&self) -> &str {
    self.msg.as_str()
  }

  fn cause(&self) -> Option<&StdError> {
    None
  }
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Token {
  session_token: String,
}

I was thinking that create_user would either return a Token or a ServerError (if username is taken for example). But I’m struggling on how to return this to the client.

Note that I’m a total noob in web dev, it’s my first attempt ever and my webdev culture is quite weak atm. But that’s the point: I want to learn :slight_smile:

#4

I know nothing about web dev or warp but I got it to compile like this:

let create_user = path!("user" / String / String).and_then(|u: String, p: String| {
    match create_user(u.as_str(), p.as_str()) {
        Ok(token) => Ok(reply::json(&token)),
        Err(e) => Err(reject::custom(e)),
    }
});

Is it working?

2 Likes
#5

I have other issues but this part is solved, thanks a lot!