2

Ok so I have an axum handler which looks somewhat like this:

#[debug_handler]
async fn handler(
    State(server_state): State<Arc<Server>>,
    Query(query_params): Query<Query>,
) -> impl IntoResponse {
    match server_state.store.handle(query_params).await {
        Ok(res) => (StatusCode::OK, Json(res)),
        Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, Json(err))
    }
}

This fails with the following error:

   |
42 | /     match server_state.store.handle(query_params).await {
43 | |         Ok(res) => (StatusCode::OK, Json(res)),
   | |                   -------------------------- this is found to be of type `(StatusCode, axum::Json<Vec<Data>>)`
44 | |         Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, Json(err))
   | |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec`, found enum `sqlx::Error`
45 | |     }
   | |_____- `match` arms have incompatible types
   |
   = note: expected tuple `(StatusCode, axum::Json<Vec<Data>>)`
              found tuple `(StatusCode, axum::Json<sqlx::Error>)`

I understand why the error is happening. The two arms of the match expression don't have the same return type.

But the question is how to fix this? I am not sure it makes sense to have to convert somehow sqlx::Error into the ok case.

The other approach I can think of is to have a response struct...something like

struct Response {
   body: Option<Data>,
   error: Option<sqlx::Error>
}

and error will be None in case of success. body will be None in case of error.

The question is, I am not sure if this is the generally acceptable way of handling this with Axum?

Finlay Weber
  • 2,989
  • 3
  • 17
  • 37
  • 1
    There is `Result` for this exact purpose. And it's [supported by axum handlers](https://docs.rs/axum/latest/axum/response/index.html#returning-different-respoinse-types) please consult the docs before posting questions here. – cafce25 Dec 31 '22 at 11:01
  • what if i told you I did but did not see this section of the docs, will you believe me? – Finlay Weber Dec 31 '22 at 11:28
  • I found it witin 2 clicks of my online search so I assumed you didn't even look, search engine foo seems to be strong with me today. If you looked and didn't find anything then I'm sorry if it came across a little harsh. – cafce25 Dec 31 '22 at 15:49

1 Answers1

5

a little bit a late answer, but i think the easiest way to do it in this case is to apply into_response() to both match-arm results:

 match server_state.store.handle(query_params).await {
    Ok(res) => (StatusCode::OK, Json(res)).into_response(),
    Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, Json(err)).into_response()
}

Best regards Thomas

mazi
  • 51
  • 2