use futures::StreamExt;
use jsonrpsee_types::{error::GenericTransportError, http::HttpConfig};
pub async fn read_response_to_body(
headers: &hyper::HeaderMap,
mut body: hyper::Body,
config: HttpConfig,
) -> Result<Vec<u8>, GenericTransportError<hyper::Error>> {
let body_size = read_header_content_length(&headers).unwrap_or(0);
if body_size > config.max_request_body_size {
return Err(GenericTransportError::TooLarge);
}
let mut received_data = Vec::with_capacity(body_size as usize);
while let Some(chunk) = body.next().await {
let chunk = chunk.map_err(|e| GenericTransportError::Inner(e))?;
let body_length = chunk.len() + received_data.len();
if body_length > config.max_request_body_size as usize {
return Err(GenericTransportError::TooLarge);
}
received_data.extend_from_slice(&chunk);
}
Ok(received_data)
}
fn read_header_content_length(headers: &hyper::header::HeaderMap) -> Option<u32> {
let length = read_header_value(headers, "content-length")?;
u32::from_str_radix(length, 10).ok()
}
pub fn read_header_value<'a>(headers: &'a hyper::header::HeaderMap, header_name: &str) -> Option<&'a str> {
let mut values = headers.get_all(header_name).iter();
let val = values.next()?;
if values.next().is_none() {
val.to_str().ok()
} else {
None
}
}
pub fn read_header_values<'a>(
headers: &'a hyper::header::HeaderMap,
header_name: &str,
) -> hyper::header::ValueIter<'a, hyper::header::HeaderValue> {
headers.get_all(header_name).iter()
}
#[cfg(test)]
mod tests {
use super::{read_header_content_length, read_response_to_body, HttpConfig};
use jsonrpsee_types::jsonrpc;
#[tokio::test]
async fn body_to_request_works() {
let s = r#"[{"a":"hello"}]"#;
let expected: jsonrpc::Request = serde_json::from_str(s).unwrap();
let body = hyper::Body::from(s.to_owned());
let headers = hyper::header::HeaderMap::new();
let bytes = read_response_to_body(&headers, body, HttpConfig::default()).await.unwrap();
let req: jsonrpc::Request = serde_json::from_slice(&bytes).unwrap();
assert_eq!(req, expected);
}
#[tokio::test]
async fn body_to_bytes_size_limit_works() {
let headers = hyper::header::HeaderMap::new();
let body = hyper::Body::from(vec![0; 128]);
assert!(read_response_to_body(&headers, body, HttpConfig { max_request_body_size: 127 }).await.is_err());
}
#[test]
fn read_content_length_works() {
let mut headers = hyper::header::HeaderMap::new();
headers.insert(hyper::header::CONTENT_LENGTH, "177".parse().unwrap());
assert_eq!(read_header_content_length(&headers), Some(177));
headers.append(hyper::header::CONTENT_LENGTH, "999".parse().unwrap());
assert_eq!(read_header_content_length(&headers), None);
}
#[test]
fn read_content_length_too_big_value() {
let mut headers = hyper::header::HeaderMap::new();
headers.insert(hyper::header::CONTENT_LENGTH, "18446744073709551616".parse().unwrap());
assert_eq!(read_header_content_length(&headers), None);
}
}