Ракетная черта Responder не реализована для Result - PullRequest
0 голосов
/ 26 марта 2020

Я недавно начал изучать Rust и сейчас пытаюсь создать небольшой API; Я создал собственную структуру для ответа API и перечислил ошибку:

// API Response Structure
pub struct ApiResponse {
    pub body: JsonValue,
    pub status: Status,
}

// Enum for my "custom errors"
#[derive(Debug, Snafu, Clone, Serialize)]
pub enum Errors {
    #[snafu(display("Unable to retrieve the specified entry."))]
    NotFound,

    #[snafu(display("Internal Server Error, unable to process the data."))]
    ISE,
}

Затем я реализовал черту Responder<'_> для моей структуры ответа API:

impl<'r> Responder<'r> for ApiResponse {
    fn respond_to(self, req: &Request) -> Result<Response<'r>, Status> {
        Response::build_from(self.body.respond_to(req).unwrap())
            .status(self.status)
            .header(ContentType::JSON)
            .ok()
    }
}

Однако, когда я пытаюсь использовать упомянутое, кажется, что моя функция не может вернуть Result<JsonValue, Errors>. Я не совсем уверен в этой проблеме, как и опыт работы с Rust, поэтому любая документация / указатели будут с благодарностью приняты.

Вот функция, которая возвращает тип ответа.

#[put("/users/<user_id>", format = "json", data = "<new_user>")]
pub fn update_user(
    conn: DbConnection,
    user_id: i32,
    new_user: Json<NewUser>,
) -> Result<JsonValue, ApiResponse> {

    match users::table.find(user_id).load::<User>(&*conn) {
        Ok(result) => {
            if result.len() < 1 {
                let response = ApiResponse {
                    body: json!({
                        "message": Errors::NotFound
                    }),
                    status: Status::NotFound
                };

                return Err(response)
            }
        },

        Err(e) => {
            let response = ApiResponse {
                body: json!({
                    "message": Errors::ISE
                }),
                status: Status::InternalServerError
            };

            return Err(response);
        },
    }

    match diesel::update(users::table.filter(id.eq(user_id)))
        .set((
            user_name.eq(new_user.user_name.to_string()),
            age.eq(new_user.age),
            gender.eq(new_user.gender.to_string()),
        ))
        .get_result::<User>(&*conn)
    {
        Ok(result) => Ok(json!(result)),
        Err(_) => {
            let res = ApiResponse {
                body: json!({
                    "message": Errors::ISE
                }),
                status: Status::InternalServerError
            };

            return Err(res);
        },
    }
}

Примечание: пожалуйста, имейте в виду, что я все еще начинающий с Rust, и моя обработка ошибок / код в целом не самая лучшая.


Редактировать: я забыл включить стек ошибок:

error[E0277]: the trait bound `std::result::Result<rocket_contrib::json::JsonValue, api_cont::ApiResponse>: rocket::response::Responder<'_>` is not satisfied
   --> src/routes.rs:72:6
    |
72  | ) -> Result<JsonValue, ApiResponse> {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `rocket::response::Responder<'_>` is not implemented for `std::result::Result<rocket_contrib::json::JsonValue, api_cont::ApiResponse>`
    | 
   ::: /home/kenneth/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.4/src/handler.rs:202:20
    |
202 |     pub fn from<T: Responder<'r>>(req: &Request, responder: T) -> Outcome<'r> {
    |                    ------------- required by this bound in `rocket::handler::<impl rocket::Outcome<rocket::Response<'r>, rocket::http::Status, rocket::Data>>::from`
    |
    = help: the following implementations were found:
              <std::result::Result<R, E> as rocket::response::Responder<'r>>
              <std::result::Result<R, E> as rocket::response::Responder<'r>>

1 Ответ

1 голос
/ 30 марта 2020

Я тоже столкнулся с этой ошибкой. В API Docs упоминается следующее:

Тип, реализующий Responder, должен реализовывать черту Debug, когда это возможно. Это связано с тем, что реализация Responder для Result требует своего типа Err для реализации Debug. Следовательно, тип, реализующий Debug, может быть проще составлен.

Это означает, что вы должны реализовать Debug, так как вы используете ApiResponse как тип Err.

#[derive(Debug)]
pub struct ApiResponse {
    pub body: JsonValue,
    pub status: Status,
}
...