@@ -23,11 +23,18 @@ pub const CONSENSUS_VERSION_HEADER: &str = "Eth-Consensus-Version";
2323
2424#[ derive( Debug , Error ) ]
2525pub enum ResponseReadError {
26- #[ error( "response size exceeds max size; max: {max}, content_length: {content_length}" ) ]
27- PayloadTooLarge { max : usize , content_length : usize } ,
26+ #[ error(
27+ "response size exceeds max size; max: {max}, content_length: {content_length}, request_url: {request_url}, request_id: {request_id}"
28+ ) ]
29+ PayloadTooLarge { max : usize , content_length : usize , request_url : String , request_id : String } ,
2830
2931 #[ error( "error reading response stream: {0}" ) ]
3032 ReqwestError ( #[ from] reqwest:: Error ) ,
33+
34+ #[ error(
35+ "request failed with status: {status_code}, request_url: {request_url}, request_id: {request_id}, body: {error_msg}"
36+ ) ]
37+ NonSuccess { status_code : u16 , error_msg : String , request_url : String , request_id : String } ,
3138}
3239
3340#[ cfg( feature = "testing-flags" ) ]
@@ -51,6 +58,8 @@ fn should_ignore_content_length() -> bool {
5158pub async fn read_chunked_body_with_max (
5259 res : Response ,
5360 max_size : usize ,
61+ request_id : & str ,
62+ request_url : & str ,
5463) -> Result < Vec < u8 > , ResponseReadError > {
5564 // Get the content length from the response headers
5665 #[ cfg( not( feature = "testing-flags" ) ) ]
@@ -72,6 +81,8 @@ pub async fn read_chunked_body_with_max(
7281 return Err ( ResponseReadError :: PayloadTooLarge {
7382 max : max_size,
7483 content_length : length as usize ,
84+ request_url : request_url. to_string ( ) ,
85+ request_id : request_id. to_string ( ) ,
7586 } ) ;
7687 }
7788
@@ -86,6 +97,8 @@ pub async fn read_chunked_body_with_max(
8697 return Err ( ResponseReadError :: PayloadTooLarge {
8798 max : max_size,
8899 content_length : content_length. unwrap_or ( 0 ) as usize ,
100+ request_url : request_url. to_string ( ) ,
101+ request_id : request_id. to_string ( ) ,
89102 } ) ;
90103 }
91104
@@ -95,6 +108,28 @@ pub async fn read_chunked_body_with_max(
95108 Ok ( response_bytes)
96109}
97110
111+ /// Reads an HTTP response body with a size limit, erroring on non-success
112+ /// status or read failure.
113+ pub async fn safe_read_http_response (
114+ response : reqwest:: Response ,
115+ max_size : usize ,
116+ request_id : & str ,
117+ ) -> Result < Vec < u8 > , ResponseReadError > {
118+ let status_code = response. status ( ) ;
119+ let request_url = response. url ( ) . to_string ( ) ;
120+ let body = read_chunked_body_with_max ( response, max_size, request_id, & request_url) . await ?;
121+ if status_code. is_success ( ) {
122+ Ok ( body)
123+ } else {
124+ Err ( ResponseReadError :: NonSuccess {
125+ status_code : status_code. as_u16 ( ) ,
126+ error_msg : String :: from_utf8_lossy ( & body) . into_owned ( ) ,
127+ request_url : request_url. to_string ( ) ,
128+ request_id : request_id. to_string ( ) ,
129+ } )
130+ }
131+ }
132+
98133/// Returns the user agent from the request headers or an empty string if not
99134/// present
100135pub fn get_user_agent ( req_headers : & HeaderMap ) -> String {
0 commit comments