This commit is contained in:
Bryan Stitt 2023-11-06 22:52:42 -08:00
parent 32778a4582
commit bbeff03452
6 changed files with 204 additions and 60 deletions

@ -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;