handle more jsonrpc errors as HTTP 200
This commit is contained in:
parent
009fdbe2cf
commit
917dfc914f
@ -167,7 +167,7 @@ impl Web3ProxyError {
|
||||
// TODO: include a unique request id in the data
|
||||
let (code, err): (StatusCode, JsonRpcErrorData) = match self {
|
||||
Self::Abi(err) => {
|
||||
warn!("abi error={:?}", err);
|
||||
warn!(?err, "abi error");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
@ -201,12 +201,12 @@ impl Web3ProxyError {
|
||||
)
|
||||
}
|
||||
Self::Anyhow(err) => {
|
||||
warn!("anyhow. err={:?}", err);
|
||||
warn!(?err, "anyhow");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
// TODO: is it safe to expose all of our anyhow strings?
|
||||
message: err.to_string().into(),
|
||||
message: "INTERNAL SERVER ERROR".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
@ -214,10 +214,10 @@ impl Web3ProxyError {
|
||||
}
|
||||
Self::Arc(err) => {
|
||||
// recurse
|
||||
return err.as_response_parts::<R>();
|
||||
return err.as_response_parts();
|
||||
}
|
||||
Self::BadRequest(err) => {
|
||||
trace!("BAD_REQUEST: {}", err);
|
||||
trace!(?err, "BAD_REQUEST");
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
JsonRpcErrorData {
|
||||
@ -229,7 +229,7 @@ impl Web3ProxyError {
|
||||
}
|
||||
Self::BadResponse(err) => {
|
||||
// TODO: think about this one more. ankr gives us this because ethers fails to parse responses without an id
|
||||
debug!("BAD_RESPONSE: {:?}", err);
|
||||
debug!(?err, "BAD_RESPONSE");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
@ -284,43 +284,52 @@ impl Web3ProxyError {
|
||||
)
|
||||
}
|
||||
Self::EthersHttpClient(err) => {
|
||||
todo!("how should we handle this error? needs to try into jsonrpcerrordata");
|
||||
|
||||
warn!("EthersHttpClientError err={:#?}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
message: "ether http client error".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
if let Ok(err) = JsonRpcErrorData::try_from(err) {
|
||||
trace!(?err, "EthersHttpClient jsonrpc error");
|
||||
(StatusCode::OK, err)
|
||||
} else {
|
||||
warn!(?err, "EthersHttpClient");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
message: "ethers http client error".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::EthersProvider(err) => {
|
||||
todo!("how should we handle this error? needs to try into jsonrpcerrordata");
|
||||
|
||||
warn!("EthersProviderError err={:#?}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
message: "ether provider error".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
if let Ok(err) = JsonRpcErrorData::try_from(err) {
|
||||
trace!(?err, "EthersProvider jsonrpc error");
|
||||
(StatusCode::OK, err)
|
||||
} else {
|
||||
warn!(?err, "EthersProvider");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
message: "ethers provider error".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::EthersWsClient(err) => {
|
||||
todo!("how should we handle this error? needs to try into jsonrpcerrordata");
|
||||
|
||||
warn!("EthersWsClientError err={:#?}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
message: "ether ws client error".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
if let Ok(err) = JsonRpcErrorData::try_from(err) {
|
||||
trace!(?err, "EthersWsClient jsonrpc error");
|
||||
(StatusCode::OK, err)
|
||||
} else {
|
||||
warn!(?err, "EthersWsClient");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
JsonRpcErrorData {
|
||||
message: "ethers ws client error".into(),
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::FlumeRecv(err) => {
|
||||
warn!("FlumeRecvError err={:#?}", err);
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::{errors::Web3ProxyError, jsonrpc::JsonRpcErrorData, rpcs::blockchain::ArcBlock};
|
||||
use derive_more::From;
|
||||
use ethers::{providers::ProviderError, types::U64};
|
||||
use ethers::{
|
||||
providers::{HttpClientError, JsonRpcError, ProviderError, WsClientError},
|
||||
types::U64,
|
||||
};
|
||||
use hashbrown::hash_map::DefaultHashBuilder;
|
||||
use moka::future::Cache;
|
||||
use serde_json::value::RawValue;
|
||||
@ -139,14 +142,15 @@ impl<R> TryFrom<Web3ProxyError> for JsonRpcResponseEnum<R> {
|
||||
type Error = Web3ProxyError;
|
||||
|
||||
fn try_from(value: Web3ProxyError) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Web3ProxyError::EthersProvider(provider_err) => {
|
||||
let err = JsonRpcErrorData::try_from(provider_err)?;
|
||||
if let Web3ProxyError::EthersProvider(ref err) = value {
|
||||
if let Ok(x) = JsonRpcErrorData::try_from(err) {
|
||||
let x = x.into();
|
||||
|
||||
Ok(err.into())
|
||||
return Ok(x);
|
||||
}
|
||||
err => Err(err),
|
||||
}
|
||||
|
||||
Err(value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,36 +197,52 @@ impl<R> From<JsonRpcErrorData> for JsonRpcResponseEnum<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ProviderError> for JsonRpcErrorData {
|
||||
type Error = Web3ProxyError;
|
||||
impl<'a> From<&'a JsonRpcError> for JsonRpcErrorData {
|
||||
fn from(value: &'a JsonRpcError) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
message: value.message.clone().into(),
|
||||
data: value.data.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from(e: ProviderError) -> Result<Self, Self::Error> {
|
||||
// TODO: move turning ClientError into json to a helper function?
|
||||
let code;
|
||||
let message: String;
|
||||
let data;
|
||||
impl<'a> TryFrom<&'a ProviderError> for JsonRpcErrorData {
|
||||
type Error = &'a ProviderError;
|
||||
|
||||
fn try_from(e: &'a ProviderError) -> Result<Self, Self::Error> {
|
||||
match e {
|
||||
ProviderError::JsonRpcClientError(err) => {
|
||||
if let Some(err) = err.as_error_response() {
|
||||
code = err.code;
|
||||
message = err.message.clone();
|
||||
data = err.data.clone();
|
||||
} else if let Some(err) = err.as_serde_error() {
|
||||
// this is not an rpc error. keep it as an error
|
||||
return Err(Web3ProxyError::BadResponse(err.to_string().into()));
|
||||
Ok(err.into())
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("unexpected ethers error! {:?}", err).into());
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
e => return Err(e.into()),
|
||||
e => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(JsonRpcErrorData {
|
||||
code,
|
||||
message: message.into(),
|
||||
data,
|
||||
})
|
||||
impl<'a> TryFrom<&'a HttpClientError> for JsonRpcErrorData {
|
||||
type Error = &'a HttpClientError;
|
||||
|
||||
fn try_from(e: &'a HttpClientError) -> Result<Self, Self::Error> {
|
||||
match e {
|
||||
HttpClientError::JsonRpcError(err) => Ok(err.into()),
|
||||
e => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a WsClientError> for JsonRpcErrorData {
|
||||
type Error = &'a WsClientError;
|
||||
|
||||
fn try_from(e: &'a WsClientError) -> Result<Self, Self::Error> {
|
||||
match e {
|
||||
WsClientError::JsonRpcError(err) => Ok(err.into()),
|
||||
e => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -946,19 +946,32 @@ impl Web3Rpcs {
|
||||
.store(is_backup_response, Ordering::Release);
|
||||
}
|
||||
|
||||
if let Some(request_metadata) = request_metadata {
|
||||
request_metadata
|
||||
.error_response
|
||||
.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
Err(error) => {
|
||||
// trace!(?response, "rpc error");
|
||||
|
||||
// TODO: separate jsonrpc error and web3 proxy error!
|
||||
// TODO: separate tracking for jsonrpc error and web3 proxy error!
|
||||
if let Some(request_metadata) = request_metadata {
|
||||
request_metadata
|
||||
.error_response
|
||||
.store(true, Ordering::Release);
|
||||
}
|
||||
|
||||
let error: JsonRpcErrorData = error.try_into()?;
|
||||
// TODO: if this is an error, do NOT return. continue to try on another server
|
||||
let error = match JsonRpcErrorData::try_from(&error) {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
warn!(?err, "error from {}", rpc);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// some errors should be retried on other nodes
|
||||
let error_msg = error.message.as_ref();
|
||||
|
Loading…
Reference in New Issue
Block a user