Add trailing metadata and fix test
This commit is contained in:
@@ -418,6 +418,7 @@ pub async fn custom_metadata(client: &mut Client, assertions: &mut Vec<TestAsser
|
|||||||
// format!("result={:?}", response.metadata().get_bin(key1))
|
// format!("result={:?}", response.metadata().get_bin(key1))
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
|
|
||||||
let response = client
|
let response = client
|
||||||
.full_duplex_call(req_stream)
|
.full_duplex_call(req_stream)
|
||||||
.await
|
.await
|
||||||
@@ -428,10 +429,17 @@ pub async fn custom_metadata(client: &mut Client, assertions: &mut Vec<TestAsser
|
|||||||
response.metadata().get(key1) == Some(&value1),
|
response.metadata().get(key1) == Some(&value1),
|
||||||
format!("result={:?}", response.metadata().get(key1))
|
format!("result={:?}", response.metadata().get(key1))
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let mut stream = response.into_inner();
|
||||||
|
|
||||||
|
// while let Some(_) = stream.next().await {}
|
||||||
|
|
||||||
|
let trailers = stream.trailers().await.unwrap().unwrap();
|
||||||
|
|
||||||
assertions.push(test_assert!(
|
assertions.push(test_assert!(
|
||||||
"metadata bin must match in unary",
|
"metadata bin must match in unary",
|
||||||
response.metadata().get_bin(key2) == Some(&value2),
|
trailers.get_bin(key2) == Some(&value2),
|
||||||
format!("result={:?}", response.metadata().get_bin(key1))
|
format!("result={:?}", trailers.get_bin(key1))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
cargo run -p tonic-interop --bin client -- \
|
cargo run -p tonic-interop --bin client -- \
|
||||||
--test_case=empty_unary,large_unary,client_streaming,server_streaming,ping_pong,\
|
--test_case=empty_unary,large_unary,client_streaming,server_streaming,ping_pong,\
|
||||||
empty_stream,status_code_and_message,special_status_message,unimplemented_method,\
|
empty_stream,status_code_and_message,special_status_message,unimplemented_method,\
|
||||||
unimplemented_service
|
unimplemented_service,custom_metadata
|
||||||
|
|
||||||
# DISABLED: ,custom_metadata
|
|
||||||
|
|||||||
+42
-22
@@ -19,6 +19,7 @@ pub struct Streaming<T> {
|
|||||||
state: State,
|
state: State,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
buf: BytesMut,
|
buf: BytesMut,
|
||||||
|
trailers: Option<MetadataMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Unpin for Streaming<T> {}
|
impl<T> Unpin for Streaming<T> {}
|
||||||
@@ -44,14 +45,7 @@ impl<T> Streaming<T> {
|
|||||||
B::Error: Into<crate::Error>,
|
B::Error: Into<crate::Error>,
|
||||||
D: Decoder<Item = T, Error = Status> + Send + 'static,
|
D: Decoder<Item = T, Error = Status> + Send + 'static,
|
||||||
{
|
{
|
||||||
Self {
|
Self::new(decoder, body, Direction::Response(status_code))
|
||||||
decoder: Box::new(decoder),
|
|
||||||
body: BoxBody::map_from(body),
|
|
||||||
state: State::ReadHeader,
|
|
||||||
direction: Direction::Response(status_code),
|
|
||||||
// FIXME: update this with a reasonable size
|
|
||||||
buf: BytesMut::with_capacity(1024 * 1024),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_empty<B, D>(decoder: D, body: B) -> Self
|
pub fn new_empty<B, D>(decoder: D, body: B) -> Self
|
||||||
@@ -61,17 +55,19 @@ impl<T> Streaming<T> {
|
|||||||
B::Error: Into<crate::Error>,
|
B::Error: Into<crate::Error>,
|
||||||
D: Decoder<Item = T, Error = Status> + Send + 'static,
|
D: Decoder<Item = T, Error = Status> + Send + 'static,
|
||||||
{
|
{
|
||||||
Self {
|
Self::new(decoder, body, Direction::EmptyResponse)
|
||||||
decoder: Box::new(decoder),
|
|
||||||
body: BoxBody::map_from(body),
|
|
||||||
state: State::ReadHeader,
|
|
||||||
direction: Direction::EmptyResponse,
|
|
||||||
// FIXME: update this with a reasonable size
|
|
||||||
buf: BytesMut::with_capacity(1024 * 1024),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_request<B, D>(decoder: D, body: B) -> Self
|
pub fn new_request<B, D>(decoder: D, body: B) -> Self
|
||||||
|
where
|
||||||
|
B: Body + Send + 'static,
|
||||||
|
B::Data: Into<Bytes>,
|
||||||
|
B::Error: Into<crate::Error>,
|
||||||
|
D: Decoder<Item = T, Error = Status> + Send + 'static,
|
||||||
|
{
|
||||||
|
Self::new(decoder, body, Direction::Request)
|
||||||
|
}
|
||||||
|
fn new<B, D>(decoder: D, body: B, direction: Direction) -> Self
|
||||||
where
|
where
|
||||||
B: Body + Send + 'static,
|
B: Body + Send + 'static,
|
||||||
B::Data: Into<Bytes>,
|
B::Data: Into<Bytes>,
|
||||||
@@ -82,23 +78,45 @@ impl<T> Streaming<T> {
|
|||||||
decoder: Box::new(decoder),
|
decoder: Box::new(decoder),
|
||||||
body: BoxBody::map_from(body),
|
body: BoxBody::map_from(body),
|
||||||
state: State::ReadHeader,
|
state: State::ReadHeader,
|
||||||
direction: Direction::Request,
|
direction,
|
||||||
// FIXME: update this with a reasonable size
|
// FIXME: update this with a reasonable size
|
||||||
buf: BytesMut::with_capacity(1024 * 1024),
|
buf: BytesMut::with_capacity(1024 * 1024),
|
||||||
|
trailers: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Streaming<T> {
|
impl<T> Streaming<T> {
|
||||||
// pub async fn message(&mut self) -> Option<Result<T::Item, Status>> {
|
pub async fn message(&mut self) -> Option<Result<T, Status>> {
|
||||||
// future::poll_fn(|cx| Pin::new(&mut *self).poll_next(cx)).await
|
future::poll_fn(|cx| Pin::new(&mut *self).poll_next(cx)).await
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub async fn trailers(&mut self) -> Result<Option<MetadataMap>, Status> {
|
pub async fn trailers(mut self) -> Result<Option<MetadataMap>, Status> {
|
||||||
|
// Shortcut to see if we already pulled the trailers in the stream step
|
||||||
|
// we need to do that so that the stream can error on trailing grpc-status
|
||||||
|
if let Some(trailers) = self.trailers {
|
||||||
|
return Ok(Some(trailers));
|
||||||
|
}
|
||||||
|
|
||||||
|
// To fetch the trailers we must clear the body and drop it.
|
||||||
|
while let Some(res) = self.message().await {
|
||||||
|
res?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we call poll_trailers internally on poll_next we need to
|
||||||
|
// check if it got cached again.
|
||||||
|
if let Some(trailers) = self.trailers {
|
||||||
|
return Ok(Some(trailers));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Trailers were not caught during poll_next and thus lets poll for
|
||||||
|
// them manually.
|
||||||
let map =
|
let map =
|
||||||
future::poll_fn(|cx| unsafe { Pin::new_unchecked(&mut self.body) }.poll_trailers(cx))
|
future::poll_fn(|cx| unsafe { Pin::new_unchecked(&mut self.body) }.poll_trailers(cx))
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Status::from_error(&e))?;
|
.map_err(|e| Status::from_error(&e))?;
|
||||||
|
|
||||||
Ok(map.map(MetadataMap::from_headers))
|
Ok(map.map(MetadataMap::from_headers))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,8 +223,10 @@ impl<T> Stream for Streaming<T> {
|
|||||||
if let Direction::Response(status) = self.direction {
|
if let Direction::Response(status) = self.direction {
|
||||||
match ready!(unsafe { Pin::new_unchecked(&mut self.body) }.poll_trailers(cx)) {
|
match ready!(unsafe { Pin::new_unchecked(&mut self.body) }.poll_trailers(cx)) {
|
||||||
Ok(trailer) => {
|
Ok(trailer) => {
|
||||||
if let Err(e) = crate::status::infer_grpc_status(trailer, status) {
|
if let Err(e) = crate::status::infer_grpc_status(trailer.as_ref(), status) {
|
||||||
return Some(Err(e)).into();
|
return Some(Err(e)).into();
|
||||||
|
} else {
|
||||||
|
self.trailers = trailer.map(MetadataMap::from_headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
+1
-1
@@ -312,7 +312,7 @@ impl Error for Status {}
|
|||||||
/// Take the `Status` value from `trailers` if it is available, else from `status_code`.
|
/// Take the `Status` value from `trailers` if it is available, else from `status_code`.
|
||||||
///
|
///
|
||||||
pub(crate) fn infer_grpc_status(
|
pub(crate) fn infer_grpc_status(
|
||||||
trailers: Option<HeaderMap>,
|
trailers: Option<&HeaderMap>,
|
||||||
status_code: http::StatusCode,
|
status_code: http::StatusCode,
|
||||||
) -> Result<(), Status> {
|
) -> Result<(), Status> {
|
||||||
if let Some(trailers) = trailers {
|
if let Some(trailers) = trailers {
|
||||||
|
|||||||
Reference in New Issue
Block a user