2022-08-16 22:29:00 +03:00
|
|
|
use crate::jsonrpc::JsonRpcForwardedResponse;
|
2022-08-10 05:37:34 +03:00
|
|
|
use axum::{
|
|
|
|
http::StatusCode,
|
|
|
|
response::{IntoResponse, Response},
|
|
|
|
Json,
|
|
|
|
};
|
2022-08-17 00:43:39 +03:00
|
|
|
use derive_more::From;
|
2022-08-17 01:52:12 +03:00
|
|
|
use redis_rate_limit::{bb8::RunError, RedisError};
|
2022-08-27 08:42:25 +03:00
|
|
|
use sea_orm::DbErr;
|
2022-06-05 22:58:47 +03:00
|
|
|
use serde_json::value::RawValue;
|
2022-08-16 22:29:00 +03:00
|
|
|
use std::error::Error;
|
2022-06-05 22:58:47 +03:00
|
|
|
|
2022-08-17 00:43:39 +03:00
|
|
|
// TODO: take "IntoResult" instead?
|
|
|
|
pub type FrontendResult = Result<Response, FrontendErrorResponse>;
|
|
|
|
|
|
|
|
#[derive(From)]
|
|
|
|
pub enum FrontendErrorResponse {
|
|
|
|
Anyhow(anyhow::Error),
|
2022-08-17 01:52:12 +03:00
|
|
|
Box(Box<dyn Error>),
|
|
|
|
// TODO: should we box these instead?
|
|
|
|
Redis(RedisError),
|
2022-08-27 08:42:25 +03:00
|
|
|
RedisRun(RunError<RedisError>),
|
2022-08-21 12:39:38 +03:00
|
|
|
Response(Response),
|
2022-08-27 08:42:25 +03:00
|
|
|
Database(DbErr),
|
2022-08-16 22:29:00 +03:00
|
|
|
}
|
|
|
|
|
2022-08-17 00:43:39 +03:00
|
|
|
impl IntoResponse for FrontendErrorResponse {
|
2022-08-16 22:29:00 +03:00
|
|
|
fn into_response(self) -> Response {
|
2022-08-17 01:52:12 +03:00
|
|
|
let null_id = RawValue::from_string("null".to_string()).unwrap();
|
|
|
|
|
|
|
|
// TODO: think more about this. this match should probably give us http and jsonrpc codes
|
|
|
|
let err = match self {
|
|
|
|
Self::Anyhow(err) => err,
|
|
|
|
Self::Box(err) => anyhow::anyhow!("Boxed error: {:?}", err),
|
|
|
|
Self::Redis(err) => err.into(),
|
2022-08-27 08:42:25 +03:00
|
|
|
Self::RedisRun(err) => err.into(),
|
2022-08-21 12:39:38 +03:00
|
|
|
Self::Response(r) => {
|
|
|
|
return r;
|
|
|
|
}
|
2022-08-27 08:42:25 +03:00
|
|
|
Self::Database(err) => err.into(),
|
2022-08-17 01:52:12 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
let err = JsonRpcForwardedResponse::from_anyhow_error(err, null_id);
|
|
|
|
|
|
|
|
let code = StatusCode::INTERNAL_SERVER_ERROR;
|
|
|
|
|
|
|
|
// TODO: logs here are too verbose. emit a stat instead? or maybe only log internal errors?
|
|
|
|
// warn!("Responding with error: {:?}", err);
|
|
|
|
|
|
|
|
(code, Json(err)).into_response()
|
2022-08-16 22:29:00 +03:00
|
|
|
}
|
|
|
|
}
|
2022-06-16 05:53:37 +03:00
|
|
|
|
2022-08-10 05:37:34 +03:00
|
|
|
pub async fn handler_404() -> Response {
|
2022-06-05 22:58:47 +03:00
|
|
|
let err = anyhow::anyhow!("nothing to see here");
|
|
|
|
|
2022-08-11 04:53:27 +03:00
|
|
|
anyhow_error_into_response(Some(StatusCode::NOT_FOUND), None, err)
|
2022-06-05 22:58:47 +03:00
|
|
|
}
|
|
|
|
|
2022-08-16 22:29:00 +03:00
|
|
|
/// TODO: generic error?
|
2022-06-05 22:58:47 +03:00
|
|
|
/// handle errors by converting them into something that implements `IntoResponse`
|
2022-07-23 02:26:04 +03:00
|
|
|
/// TODO: use this. i can't get <https://docs.rs/axum/latest/axum/error_handling/index.html> to work
|
2022-06-06 01:39:44 +03:00
|
|
|
/// TODO: i think we want a custom result type instead. put the anyhow result inside. then `impl IntoResponse for CustomResult`
|
2022-08-11 04:53:27 +03:00
|
|
|
pub fn anyhow_error_into_response(
|
2022-08-06 08:26:43 +03:00
|
|
|
http_code: Option<StatusCode>,
|
2022-07-07 06:29:47 +03:00
|
|
|
id: Option<Box<RawValue>>,
|
2022-07-07 06:22:09 +03:00
|
|
|
err: anyhow::Error,
|
2022-08-10 05:37:34 +03:00
|
|
|
) -> Response {
|
2022-07-07 06:29:47 +03:00
|
|
|
// TODO: we might have an id. like if this is for rate limiting, we can use it
|
|
|
|
let id = id.unwrap_or_else(|| RawValue::from_string("null".to_string()).unwrap());
|
2022-06-05 22:58:47 +03:00
|
|
|
|
|
|
|
let err = JsonRpcForwardedResponse::from_anyhow_error(err, id);
|
|
|
|
|
2022-07-07 06:29:47 +03:00
|
|
|
// TODO: logs here are too verbose. emit a stat
|
|
|
|
// warn!("Responding with error: {:?}", err);
|
2022-06-05 22:58:47 +03:00
|
|
|
|
2022-08-06 08:26:43 +03:00
|
|
|
let code = http_code.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
|
2022-06-05 22:58:47 +03:00
|
|
|
|
2022-08-10 05:37:34 +03:00
|
|
|
(code, Json(err)).into_response()
|
2022-06-05 22:58:47 +03:00
|
|
|
}
|