mirror of
https://github.com/Noratrieb/icefun.git
synced 2026-01-15 13:15:01 +01:00
private
This commit is contained in:
parent
25adea4103
commit
7af1274587
160 changed files with 38999 additions and 4 deletions
82
hyper/src/body/to_bytes.rs
Normal file
82
hyper/src/body/to_bytes.rs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
use bytes::{Buf, BufMut, Bytes};
|
||||
|
||||
use super::HttpBody;
|
||||
|
||||
/// Concatenate the buffers from a body into a single `Bytes` asynchronously.
|
||||
///
|
||||
/// This may require copying the data into a single buffer. If you don't need
|
||||
/// a contiguous buffer, prefer the [`aggregate`](crate::body::aggregate())
|
||||
/// function.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Care needs to be taken if the remote is untrusted. The function doesn't implement any length
|
||||
/// checks and an malicious peer might make it consume arbitrary amounts of memory. Checking the
|
||||
/// `Content-Length` is a possibility, but it is not strictly mandated to be present.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # #[cfg(all(feature = "client", feature = "tcp", any(feature = "http1", feature = "http2")))]
|
||||
/// # async fn doc() -> hyper::Result<()> {
|
||||
/// use hyper::{body::HttpBody};
|
||||
///
|
||||
/// # let request = hyper::Request::builder()
|
||||
/// # .method(hyper::Method::POST)
|
||||
/// # .uri("http://httpbin.org/post")
|
||||
/// # .header("content-type", "application/json")
|
||||
/// # .body(hyper::Body::from(r#"{"library":"hyper"}"#)).unwrap();
|
||||
/// # let client = hyper::Client::new();
|
||||
/// let response = client.request(request).await?;
|
||||
///
|
||||
/// const MAX_ALLOWED_RESPONSE_SIZE: u64 = 1024;
|
||||
///
|
||||
/// let response_content_length = match response.body().size_hint().upper() {
|
||||
/// Some(v) => v,
|
||||
/// None => MAX_ALLOWED_RESPONSE_SIZE + 1 // Just to protect ourselves from a malicious response
|
||||
/// };
|
||||
///
|
||||
/// if response_content_length < MAX_ALLOWED_RESPONSE_SIZE {
|
||||
/// let body_bytes = hyper::body::to_bytes(response.into_body()).await?;
|
||||
/// println!("body: {:?}", body_bytes);
|
||||
/// }
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub async fn to_bytes<T>(body: T) -> Result<Bytes, T::Error>
|
||||
where
|
||||
T: HttpBody,
|
||||
{
|
||||
futures_util::pin_mut!(body);
|
||||
|
||||
// If there's only 1 chunk, we can just return Buf::to_bytes()
|
||||
let mut first = if let Some(buf) = body.data().await {
|
||||
buf?
|
||||
} else {
|
||||
return Ok(Bytes::new());
|
||||
};
|
||||
|
||||
let second = if let Some(buf) = body.data().await {
|
||||
buf?
|
||||
} else {
|
||||
return Ok(first.copy_to_bytes(first.remaining()));
|
||||
};
|
||||
|
||||
// Don't pre-emptively reserve *too* much.
|
||||
let rest = (body.size_hint().lower() as usize).min(1024 * 16);
|
||||
let cap = first
|
||||
.remaining()
|
||||
.saturating_add(second.remaining())
|
||||
.saturating_add(rest);
|
||||
// With more than 1 buf, we gotta flatten into a Vec first.
|
||||
let mut vec = Vec::with_capacity(cap);
|
||||
vec.put(first);
|
||||
vec.put(second);
|
||||
|
||||
while let Some(buf) = body.data().await {
|
||||
vec.put(buf?);
|
||||
}
|
||||
|
||||
Ok(vec.into())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue