wip
This commit is contained in:
parent
32778a4582
commit
bbeff03452
@ -1288,7 +1288,7 @@ impl App {
|
|||||||
// TODO: refresh the request here?
|
// TODO: refresh the request here?
|
||||||
|
|
||||||
// turn some of the Web3ProxyErrors into Ok results
|
// turn some of the Web3ProxyErrors into Ok results
|
||||||
match self._proxy_request_with_caching(&web3_request).await {
|
match self._proxy_request_with_caching(web3_request).await {
|
||||||
Ok(response_data) => {
|
Ok(response_data) => {
|
||||||
last_success = Some(response_data);
|
last_success = Some(response_data);
|
||||||
break;
|
break;
|
||||||
@ -1308,8 +1308,31 @@ impl App {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: refresh the request instead of making new each time. then we need less clones
|
||||||
|
web3_request_result = ValidatedRequest::new_with_app(
|
||||||
|
self,
|
||||||
|
authorization.clone(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
request.clone().into(),
|
||||||
|
head_block.clone(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let web3_request = match web3_request_result {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(err) => {
|
||||||
|
// i don't think we can get here, but just in case
|
||||||
|
let (a, b) = err.as_json_response_parts(error_id, Some(&request));
|
||||||
|
|
||||||
|
let rpcs = vec![];
|
||||||
|
|
||||||
|
return (a, b, rpcs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let last_response = if let Some(last_success) = last_success {
|
let last_response = if let Some(last_success) = last_success {
|
||||||
Ok(last_success)
|
Ok(last_success)
|
||||||
} else {
|
} else {
|
||||||
@ -1335,7 +1358,7 @@ impl App {
|
|||||||
.user_error_response
|
.user_error_response
|
||||||
.store(false, Ordering::SeqCst);
|
.store(false, Ordering::SeqCst);
|
||||||
|
|
||||||
err.as_json_response_parts(web3_request.id())
|
err.as_json_response_parts(web3_request.id(), Some(web3_request.as_ref()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
use crate::block_number::BlockNumOrHash;
|
use crate::block_number::BlockNumOrHash;
|
||||||
use crate::frontend::authorization::Authorization;
|
use crate::frontend::authorization::Authorization;
|
||||||
use crate::jsonrpc::{self, JsonRpcErrorData, ParsedResponse, StreamResponse};
|
use crate::jsonrpc::{
|
||||||
|
self, JsonRpcErrorData, ParsedResponse, SingleRequest, StreamResponse, ValidatedRequest,
|
||||||
|
};
|
||||||
use crate::response_cache::ForwardedResponse;
|
use crate::response_cache::ForwardedResponse;
|
||||||
use crate::rpcs::blockchain::Web3ProxyBlock;
|
use crate::rpcs::blockchain::Web3ProxyBlock;
|
||||||
use crate::rpcs::one::Web3Rpc;
|
use crate::rpcs::one::Web3Rpc;
|
||||||
@ -26,6 +28,7 @@ use redis_rate_limiter::redis::RedisError;
|
|||||||
use redis_rate_limiter::RedisPoolError;
|
use redis_rate_limiter::RedisPoolError;
|
||||||
use reqwest::header::ToStrError;
|
use reqwest::header::ToStrError;
|
||||||
use rust_decimal::Error as DecimalError;
|
use rust_decimal::Error as DecimalError;
|
||||||
|
use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::value::RawValue;
|
use serde_json::value::RawValue;
|
||||||
use siwe::VerificationError;
|
use siwe::VerificationError;
|
||||||
@ -215,12 +218,31 @@ pub enum Web3ProxyError {
|
|||||||
WithContext(Option<Box<Web3ProxyError>>, Cow<'static, str>),
|
WithContext(Option<Box<Web3ProxyError>>, Cow<'static, str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, From, Serialize)]
|
||||||
|
pub enum RequestForError<'a> {
|
||||||
|
/// sometimes we don't have a request object at all
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
/// sometimes parsing the request fails. Give them the original string
|
||||||
|
Unparsed(&'a str),
|
||||||
|
/// sometimes we have json
|
||||||
|
SingleRequest(&'a SingleRequest),
|
||||||
|
// sometimes we have json for a batch of requests
|
||||||
|
// Batch(&'a BatchRequest),
|
||||||
|
/// assuming things went well, we have a validated request
|
||||||
|
Validated(&'a ValidatedRequest),
|
||||||
|
}
|
||||||
|
|
||||||
impl Web3ProxyError {
|
impl Web3ProxyError {
|
||||||
pub fn as_json_response_parts(
|
pub fn as_json_response_parts<'a, R>(
|
||||||
&self,
|
&self,
|
||||||
id: Box<RawValue>,
|
id: Box<RawValue>,
|
||||||
) -> (StatusCode, jsonrpc::SingleResponse) {
|
request_for_error: Option<R>,
|
||||||
let (code, response_data) = self.as_response_parts();
|
) -> (StatusCode, jsonrpc::SingleResponse)
|
||||||
|
where
|
||||||
|
R: Into<RequestForError<'a>>,
|
||||||
|
{
|
||||||
|
let (code, response_data) = self.as_response_parts(request_for_error);
|
||||||
let response = jsonrpc::ParsedResponse::from_response_data(response_data, id);
|
let response = jsonrpc::ParsedResponse::from_response_data(response_data, id);
|
||||||
(code, response.into())
|
(code, response.into())
|
||||||
}
|
}
|
||||||
@ -228,7 +250,16 @@ impl Web3ProxyError {
|
|||||||
/// turn the error into an axum response.
|
/// turn the error into an axum response.
|
||||||
/// <https://www.jsonrpc.org/specification#error_object>
|
/// <https://www.jsonrpc.org/specification#error_object>
|
||||||
/// TODO? change to `to_response_parts(self)`
|
/// TODO? change to `to_response_parts(self)`
|
||||||
pub fn as_response_parts(&self) -> (StatusCode, ForwardedResponse<Arc<RawValue>>) {
|
pub fn as_response_parts<'a, R>(
|
||||||
|
&self,
|
||||||
|
request_for_error: Option<R>,
|
||||||
|
) -> (StatusCode, ForwardedResponse<Arc<RawValue>>)
|
||||||
|
where
|
||||||
|
R: Into<RequestForError<'a>>,
|
||||||
|
{
|
||||||
|
let request_for_error: RequestForError<'_> =
|
||||||
|
request_for_error.map(Into::into).unwrap_or_default();
|
||||||
|
|
||||||
// TODO: include a unique request id in the data
|
// TODO: include a unique request id in the data
|
||||||
let (code, err): (StatusCode, JsonRpcErrorData) = match self {
|
let (code, err): (StatusCode, JsonRpcErrorData) = match self {
|
||||||
Self::Abi(err) => {
|
Self::Abi(err) => {
|
||||||
@ -238,7 +269,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "abi error".into(),
|
message: "abi error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -250,7 +284,9 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: format!("FORBIDDEN: {}", msg).into(),
|
message: format!("FORBIDDEN: {}", msg).into(),
|
||||||
code: StatusCode::FORBIDDEN.as_u16().into(),
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
||||||
data: None,
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -263,6 +299,7 @@ impl Web3ProxyError {
|
|||||||
message: "Archive data required".into(),
|
message: "Archive data required".into(),
|
||||||
code: StatusCode::OK.as_u16().into(),
|
code: StatusCode::OK.as_u16().into(),
|
||||||
data: Some(json!({
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
"min": min,
|
"min": min,
|
||||||
"max": max,
|
"max": max,
|
||||||
})),
|
})),
|
||||||
@ -277,12 +314,15 @@ impl Web3ProxyError {
|
|||||||
// TODO: is it safe to expose all of our anyhow strings?
|
// TODO: is it safe to expose all of our anyhow strings?
|
||||||
message: "INTERNAL SERVER ERROR".into(),
|
message: "INTERNAL SERVER ERROR".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Self::Arc(err) => {
|
Self::Arc(err) => {
|
||||||
return err.as_response_parts();
|
return err.as_response_parts(Some(request_for_error));
|
||||||
}
|
}
|
||||||
Self::BadRequest(err) => {
|
Self::BadRequest(err) => {
|
||||||
trace!(?err, "BAD_REQUEST");
|
trace!(?err, "BAD_REQUEST");
|
||||||
@ -291,7 +331,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "bad request".into(),
|
message: "bad request".into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -303,7 +346,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "bad response".into(),
|
message: "bad response".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -314,7 +360,9 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "bad routing".into(),
|
message: "bad routing".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: None,
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -325,7 +373,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "contract error".into(),
|
message: "contract error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -336,7 +387,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "database error!".into(),
|
message: "database error!".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -347,7 +401,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "database (arc) error!".into(),
|
message: "database (arc) error!".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -358,7 +415,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "decimal error".into(),
|
message: "decimal error".into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -374,7 +434,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "ethers http client error".into(),
|
message: "ethers http client error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -391,7 +454,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "ethers provider error".into(),
|
message: "ethers provider error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -408,7 +474,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "ethers ws client error".into(),
|
message: "ethers ws client error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -423,6 +492,7 @@ impl Web3ProxyError {
|
|||||||
data: Some(json!({
|
data: Some(json!({
|
||||||
"head": head,
|
"head": head,
|
||||||
"requested": requested,
|
"requested": requested,
|
||||||
|
"request": request_for_error,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -435,7 +505,9 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "gas estimate result is not an U256".into(),
|
message: "gas estimate result is not an U256".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: None,
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -446,7 +518,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "hdr record error".into(),
|
message: "hdr record error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -457,7 +532,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "headers error".into(),
|
message: "headers error".into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -468,7 +546,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "header to string error".into(),
|
message: "header to string error".into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -479,7 +560,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: err.to_string().into(),
|
message: err.to_string().into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -491,7 +575,10 @@ impl Web3ProxyError {
|
|||||||
// TODO: is it safe to expose these error strings?
|
// TODO: is it safe to expose these error strings?
|
||||||
message: err.to_string().into(),
|
message: err.to_string().into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -503,7 +590,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "influxdb2 error!".into(),
|
message: "influxdb2 error!".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -517,6 +607,7 @@ impl Web3ProxyError {
|
|||||||
data: Some(json!({
|
data: Some(json!({
|
||||||
"min": min,
|
"min": min,
|
||||||
"max": max,
|
"max": max,
|
||||||
|
"request": request_for_error,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -528,7 +619,9 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: err.to_string().into(),
|
message: err.to_string().into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: None,
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -539,7 +632,9 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "IP is not allowed!".into(),
|
message: "IP is not allowed!".into(),
|
||||||
code: StatusCode::FORBIDDEN.as_u16().into(),
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(ip.to_string())),
|
data: Some(json!({
|
||||||
|
"ip": ip
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -550,7 +645,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "invalid header value".into(),
|
message: "invalid header value".into(),
|
||||||
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -584,7 +682,10 @@ impl Web3ProxyError {
|
|||||||
message: "std io".into(),
|
message: "std io".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
// TODO: is it safe to expose our io error strings?
|
// TODO: is it safe to expose our io error strings?
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -683,7 +784,10 @@ impl Web3ProxyError {
|
|||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
code: code.into(),
|
code: code.into(),
|
||||||
data: Some(serde_json::Value::String(err.to_string())),
|
data: Some(json!({
|
||||||
|
"request": request_for_error,
|
||||||
|
"err": err.to_string(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -724,9 +828,12 @@ impl Web3ProxyError {
|
|||||||
(
|
(
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
JsonRpcErrorData {
|
JsonRpcErrorData {
|
||||||
message: "Blocks here must have a number or hash".into(),
|
message: "Internal server error".into(),
|
||||||
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
||||||
data: None,
|
data: Some(json!({
|
||||||
|
"err": "Blocks here must have a number or hash",
|
||||||
|
"extra": "you found a bug. please contact us if you see this and we can help figure out what happened. https://discord.llamanodes.com/",
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1261,7 +1368,7 @@ impl Web3ProxyError {
|
|||||||
Self::WithContext(err, msg) => match err {
|
Self::WithContext(err, msg) => match err {
|
||||||
Some(err) => {
|
Some(err) => {
|
||||||
warn!(?err, %msg, "error w/ context");
|
warn!(?err, %msg, "error w/ context");
|
||||||
return err.as_response_parts();
|
return err.as_response_parts(Some(request_for_error));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
warn!(%msg, "error w/ context");
|
warn!(%msg, "error w/ context");
|
||||||
@ -1280,9 +1387,15 @@ impl Web3ProxyError {
|
|||||||
(code, ForwardedResponse::from(err))
|
(code, ForwardedResponse::from(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn into_response_with_id<'a, R>(
|
||||||
pub fn into_response_with_id(self, id: Option<Box<RawValue>>) -> Response {
|
self,
|
||||||
let (status_code, response_data) = self.as_response_parts();
|
id: Option<Box<RawValue>>,
|
||||||
|
request_for_error: Option<R>,
|
||||||
|
) -> Response
|
||||||
|
where
|
||||||
|
R: Into<RequestForError<'a>>,
|
||||||
|
{
|
||||||
|
let (status_code, response_data) = self.as_response_parts(request_for_error);
|
||||||
|
|
||||||
let id = id.unwrap_or_default();
|
let id = id.unwrap_or_default();
|
||||||
|
|
||||||
@ -1292,7 +1405,7 @@ impl Web3ProxyError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// some things should keep going even if the db is down
|
/// some things should keep going even if the db is down
|
||||||
pub fn split_db_errors(&self) -> Result<&Self, &Self> {
|
pub fn ok_db_errors(&self) -> Result<&Self, &Self> {
|
||||||
match self {
|
match self {
|
||||||
Web3ProxyError::NoDatabaseConfigured => Ok(self),
|
Web3ProxyError::NoDatabaseConfigured => Ok(self),
|
||||||
Web3ProxyError::Database(err) => {
|
Web3ProxyError::Database(err) => {
|
||||||
@ -1305,7 +1418,7 @@ impl Web3ProxyError {
|
|||||||
}
|
}
|
||||||
Web3ProxyError::Arc(x) => {
|
Web3ProxyError::Arc(x) => {
|
||||||
// errors from inside moka cache helpers are wrapped in an Arc
|
// errors from inside moka cache helpers are wrapped in an Arc
|
||||||
x.split_db_errors()
|
x.ok_db_errors()
|
||||||
}
|
}
|
||||||
_ => Err(self),
|
_ => Err(self),
|
||||||
}
|
}
|
||||||
@ -1326,8 +1439,9 @@ impl From<tokio::time::error::Elapsed> for Web3ProxyError {
|
|||||||
|
|
||||||
impl IntoResponse for Web3ProxyError {
|
impl IntoResponse for Web3ProxyError {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
/// TODO: maybe we don't want this anymore. maybe we want to require a web3_request?
|
||||||
fn into_response(self) -> Response {
|
fn into_response(self) -> Response {
|
||||||
self.into_response_with_id(Default::default())
|
self.into_response_with_id(Default::default(), RequestForError::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,8 +1465,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Web3ProxyError {
|
impl Web3ProxyError {
|
||||||
pub fn into_message(self, id: Option<Box<RawValue>>) -> Message {
|
pub fn into_message<'a, R>(self, id: Option<Box<RawValue>>, web3_request: R) -> Message
|
||||||
let (_, err) = self.as_response_parts();
|
where
|
||||||
|
R: Into<RequestForError<'a>>,
|
||||||
|
{
|
||||||
|
let (_, err) = self.as_response_parts(web3_request);
|
||||||
|
|
||||||
let id = id.unwrap_or_default();
|
let id = id.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use super::rpc_proxy_ws::ProxyMode;
|
|||||||
use crate::app::{App, APP_USER_AGENT};
|
use crate::app::{App, APP_USER_AGENT};
|
||||||
use crate::balance::Balance;
|
use crate::balance::Balance;
|
||||||
use crate::caches::RegisteredUserRateLimitKey;
|
use crate::caches::RegisteredUserRateLimitKey;
|
||||||
use crate::errors::{Web3ProxyError, Web3ProxyErrorContext, Web3ProxyResult};
|
use crate::errors::{RequestForError, Web3ProxyError, Web3ProxyErrorContext, Web3ProxyResult};
|
||||||
use crate::globals::global_db_replica_conn;
|
use crate::globals::global_db_replica_conn;
|
||||||
use crate::jsonrpc::{self, SingleRequest};
|
use crate::jsonrpc::{self, SingleRequest};
|
||||||
use crate::secrets::RpcSecretKey;
|
use crate::secrets::RpcSecretKey;
|
||||||
@ -192,7 +192,7 @@ impl ResponseOrBytes<'_> {
|
|||||||
Self::Response(x) => x.num_bytes(),
|
Self::Response(x) => x.num_bytes(),
|
||||||
Self::Bytes(num_bytes) => *num_bytes,
|
Self::Bytes(num_bytes) => *num_bytes,
|
||||||
Self::Error(x) => {
|
Self::Error(x) => {
|
||||||
let (_, x) = x.as_response_parts();
|
let (_, x) = x.as_response_parts(RequestForError::None);
|
||||||
|
|
||||||
x.num_bytes()
|
x.num_bytes()
|
||||||
}
|
}
|
||||||
@ -894,7 +894,7 @@ impl App {
|
|||||||
let authorization_checks = match self.authorization_checks(proxy_mode, rpc_key).await {
|
let authorization_checks = match self.authorization_checks(proxy_mode, rpc_key).await {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let Ok(_err) = err.split_db_errors() {
|
if let Ok(_err) = err.ok_db_errors() {
|
||||||
// // TODO: this is too verbose during an outage. the warnings on the config reloader should be fine
|
// // TODO: this is too verbose during an outage. the warnings on the config reloader should be fine
|
||||||
// warn!(
|
// warn!(
|
||||||
// ?err,
|
// ?err,
|
||||||
|
@ -81,6 +81,7 @@ pub async fn versus_proxy_web3_rpc(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: refactor this to use the builder pattern
|
||||||
async fn _proxy_web3_rpc(
|
async fn _proxy_web3_rpc(
|
||||||
app: Arc<App>,
|
app: Arc<App>,
|
||||||
ip: &IpAddr,
|
ip: &IpAddr,
|
||||||
@ -91,14 +92,14 @@ async fn _proxy_web3_rpc(
|
|||||||
) -> Result<Response, Response> {
|
) -> Result<Response, Response> {
|
||||||
// TODO: create a stat if they error. (but we haven't parsed rpc_key yet, so it needs some thought)
|
// TODO: create a stat if they error. (but we haven't parsed rpc_key yet, so it needs some thought)
|
||||||
let payload = payload
|
let payload = payload
|
||||||
.map_err(|e| Web3ProxyError::from(e).into_response_with_id(None))?
|
.map_err(|e| Web3ProxyError::from(e).into_response_with_id(None, None))?
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
let first_id = payload.first_id();
|
let first_id = payload.first_id();
|
||||||
|
|
||||||
let authorization = ip_is_authorized(&app, ip, origin, proxy_mode)
|
let authorization = ip_is_authorized(&app, ip, origin, proxy_mode)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.into_response_with_id(first_id.clone()))?;
|
.map_err(|e| e.into_response_with_id(first_id.clone(), None))?;
|
||||||
|
|
||||||
let authorization = Arc::new(authorization);
|
let authorization = Arc::new(authorization);
|
||||||
|
|
||||||
@ -109,10 +110,11 @@ async fn _proxy_web3_rpc(
|
|||||||
// TODO: calculate payload bytes here (before turning into serde_json::Value). that will save serializing later
|
// TODO: calculate payload bytes here (before turning into serde_json::Value). that will save serializing later
|
||||||
|
|
||||||
// TODO: is first_id the right thing to attach to this error?
|
// TODO: is first_id the right thing to attach to this error?
|
||||||
|
// TODO: i think we want to attach the web3_request here. but that means we need to create it here
|
||||||
let (status_code, response, rpcs) = app
|
let (status_code, response, rpcs) = app
|
||||||
.proxy_web3_rpc(authorization, payload, Some(request_id))
|
.proxy_web3_rpc(authorization, payload, Some(request_id))
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.into_response_with_id(first_id))?;
|
.map_err(|e| e.into_response_with_id(first_id, None))?;
|
||||||
|
|
||||||
let mut response = (status_code, response).into_response();
|
let mut response = (status_code, response).into_response();
|
||||||
|
|
||||||
@ -282,6 +284,7 @@ pub async fn versus_proxy_web3_rpc_with_key(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: refactor this to use the builder pattern
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
async fn _proxy_web3_rpc_with_key(
|
async fn _proxy_web3_rpc_with_key(
|
||||||
app: Arc<App>,
|
app: Arc<App>,
|
||||||
@ -297,19 +300,19 @@ async fn _proxy_web3_rpc_with_key(
|
|||||||
// TODO: DRY w/ proxy_web3_rpc
|
// TODO: DRY w/ proxy_web3_rpc
|
||||||
// TODO: create a stat if they error. (but we haven't parsed rpc_key yet, so it needs some thought)
|
// TODO: create a stat if they error. (but we haven't parsed rpc_key yet, so it needs some thought)
|
||||||
let payload = payload
|
let payload = payload
|
||||||
.map_err(|e| Web3ProxyError::from(e).into_response_with_id(None))?
|
.map_err(|e| Web3ProxyError::from(e).into_response_with_id(None, None))?
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
let first_id = payload.first_id();
|
let first_id = payload.first_id();
|
||||||
|
|
||||||
let rpc_key = rpc_key
|
let rpc_key = rpc_key
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e: Web3ProxyError| e.into_response_with_id(first_id.clone()))?;
|
.map_err(|e: Web3ProxyError| e.into_response_with_id(first_id.clone(), None))?;
|
||||||
|
|
||||||
let authorization =
|
let authorization =
|
||||||
key_is_authorized(&app, &rpc_key, ip, origin, proxy_mode, referer, user_agent)
|
key_is_authorized(&app, &rpc_key, ip, origin, proxy_mode, referer, user_agent)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.into_response_with_id(first_id.clone()))?;
|
.map_err(|e| e.into_response_with_id(first_id.clone(), None))?;
|
||||||
|
|
||||||
let authorization = Arc::new(authorization);
|
let authorization = Arc::new(authorization);
|
||||||
|
|
||||||
@ -319,10 +322,11 @@ async fn _proxy_web3_rpc_with_key(
|
|||||||
|
|
||||||
let rpc_secret_key_id = authorization.checks.rpc_secret_key_id;
|
let rpc_secret_key_id = authorization.checks.rpc_secret_key_id;
|
||||||
|
|
||||||
|
// TODO: pass web3_request to the map_err
|
||||||
let (status_code, response, rpcs) = app
|
let (status_code, response, rpcs) = app
|
||||||
.proxy_web3_rpc(authorization, payload, Some(request_id))
|
.proxy_web3_rpc(authorization, payload, Some(request_id))
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.into_response_with_id(first_id))?;
|
.map_err(|e| e.into_response_with_id(first_id, None))?;
|
||||||
|
|
||||||
let mut response = (status_code, response).into_response();
|
let mut response = (status_code, response).into_response();
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! WebSockets are the preferred method of receiving requests, but not all clients have good support.
|
//! WebSockets are the preferred method of receiving requests, but not all clients have good support.
|
||||||
|
|
||||||
use super::authorization::{ip_is_authorized, key_is_authorized, Authorization};
|
use super::authorization::{ip_is_authorized, key_is_authorized, Authorization};
|
||||||
use crate::errors::{Web3ProxyError, Web3ProxyResponse};
|
use crate::errors::{RequestForError, Web3ProxyError, Web3ProxyResponse};
|
||||||
use crate::jsonrpc::{self, ParsedResponse, ValidatedRequest};
|
use crate::jsonrpc::{self, ParsedResponse, ValidatedRequest};
|
||||||
use crate::{app::App, errors::Web3ProxyResult, jsonrpc::SingleRequest};
|
use crate::{app::App, errors::Web3ProxyResult, jsonrpc::SingleRequest};
|
||||||
use axum::headers::{Origin, Referer, UserAgent};
|
use axum::headers::{Origin, Referer, UserAgent};
|
||||||
@ -448,7 +448,7 @@ async fn handle_socket_payload(
|
|||||||
let response_str = match response {
|
let response_str = match response {
|
||||||
Ok(x) => x.to_json_string().await?,
|
Ok(x) => x.to_json_string().await?,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let (_, response_data) = err.as_response_parts();
|
let (_, response_data) = err.as_response_parts(RequestForError::None);
|
||||||
|
|
||||||
let response = ParsedResponse::from_response_data(response_data, response_id);
|
let response = ParsedResponse::from_response_data(response_data, response_id);
|
||||||
|
|
||||||
@ -498,7 +498,7 @@ async fn read_web3_socket(
|
|||||||
Ok((m, s)) => (m, Some(s)),
|
Ok((m, s)) => (m, Some(s)),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// TODO: how can we get the id out of the payload?
|
// TODO: how can we get the id out of the payload?
|
||||||
let m = err.into_message(None);
|
let m = err.into_message(None, None);
|
||||||
(m, None)
|
(m, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -532,7 +532,7 @@ async fn read_web3_socket(
|
|||||||
Ok((m, s)) => (m, Some(s)),
|
Ok((m, s)) => (m, Some(s)),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// TODO: how can we get the id out of the payload?
|
// TODO: how can we get the id out of the payload?
|
||||||
let m = err.into_message(None);
|
let m = err.into_message(None, None);
|
||||||
(m, None)
|
(m, None)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::LooseId;
|
use super::LooseId;
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::errors::Web3ProxyError;
|
use crate::errors::{Web3ProxyError, RequestForError};
|
||||||
use crate::frontend::authorization::{Authorization, RequestOrMethod};
|
use crate::frontend::authorization::{Authorization, RequestOrMethod};
|
||||||
use crate::jsonrpc::ValidatedRequest;
|
use crate::jsonrpc::ValidatedRequest;
|
||||||
use axum::response::Response as AxumResponse;
|
use axum::response::Response as AxumResponse;
|
||||||
@ -142,7 +142,7 @@ impl JsonRpcRequestEnum {
|
|||||||
|
|
||||||
request.add_response(&response);
|
request.add_response(&response);
|
||||||
|
|
||||||
let response = response.into_response_with_id(Some(err_id));
|
let response = response.into_response_with_id(Some(err_id), RequestForError::None);
|
||||||
|
|
||||||
// TODO: variable duration depending on the IP
|
// TODO: variable duration depending on the IP
|
||||||
sleep(duration).await;
|
sleep(duration).await;
|
||||||
|
Loading…
Reference in New Issue
Block a user