@@ -119,19 +119,26 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now that we know length, we can write the header
|
// now that we know length, we can write the header
|
||||||
Ok(finish_encoding(compression_encoding, buf))
|
finish_encoding(compression_encoding, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_encoding(compression_encoding: Option<CompressionEncoding>, buf: &mut BytesMut) -> Bytes {
|
fn finish_encoding(
|
||||||
|
compression_encoding: Option<CompressionEncoding>,
|
||||||
|
buf: &mut BytesMut,
|
||||||
|
) -> Result<Bytes, Status> {
|
||||||
let len = buf.len() - HEADER_SIZE;
|
let len = buf.len() - HEADER_SIZE;
|
||||||
assert!(len <= std::u32::MAX as usize);
|
if len > std::u32::MAX as usize {
|
||||||
|
return Err(Status::resource_exhausted(format!(
|
||||||
|
"Cannot return body with more than 4GB of data but got {len} bytes"
|
||||||
|
)));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let mut buf = &mut buf[..HEADER_SIZE];
|
let mut buf = &mut buf[..HEADER_SIZE];
|
||||||
buf.put_u8(compression_encoding.is_some() as u8);
|
buf.put_u8(compression_encoding.is_some() as u8);
|
||||||
buf.put_u32(len as u32);
|
buf.put_u32(len as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.split_to(len + HEADER_SIZE).freeze()
|
Ok(buf.split_to(len + HEADER_SIZE).freeze())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -136,6 +136,39 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip on windows because CI stumbles over our 4GB allocation
|
||||||
|
#[cfg(not(target_family = "windows"))]
|
||||||
|
#[tokio::test]
|
||||||
|
async fn encode_too_big() {
|
||||||
|
let encoder = MockEncoder::default();
|
||||||
|
|
||||||
|
let msg = vec![0u8; u32::MAX as usize + 1];
|
||||||
|
|
||||||
|
let messages = std::iter::once(Ok::<_, Status>(msg));
|
||||||
|
let source = futures_util::stream::iter(messages);
|
||||||
|
|
||||||
|
let body = encode_server(
|
||||||
|
encoder,
|
||||||
|
source,
|
||||||
|
None,
|
||||||
|
SingleMessageCompressionOverride::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
futures_util::pin_mut!(body);
|
||||||
|
|
||||||
|
assert!(body.data().await.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
body.trailers()
|
||||||
|
.await
|
||||||
|
.expect("no error polling trailers")
|
||||||
|
.expect("some trailers")
|
||||||
|
.get("grpc-status")
|
||||||
|
.expect("grpc-status header"),
|
||||||
|
"8"
|
||||||
|
);
|
||||||
|
assert!(body.is_end_stream());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
struct MockEncoder;
|
struct MockEncoder;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user