Check response trailers

This commit is contained in:
Lucio Franco
2019-08-18 01:47:40 -04:00
parent ef87a558e7
commit 4835be515f
5 changed files with 85 additions and 19 deletions
+17 -6
View File
@@ -1,6 +1,6 @@
use crate::{
body::{Body, BoxBody},
codec::{decode, encode, Codec, Streaming},
codec::{decode_response, decode_empty, encode, Codec, Streaming},
Code, GrpcService, Request, Response, Status,
};
use futures_core::Stream;
@@ -136,18 +136,29 @@ impl<T> Grpc<T> {
.await
.map_err(|err| Status::from_error(&*(err.into())))?;
// TODO: implement decode with status
let _status_code = response.status();
let status_code = response.status();
let trailers_only_status = Status::from_header_map(response.headers());
if let Some(status) = trailers_only_status {
let expect_additional_trailers = if let Some(status) = trailers_only_status {
if status.code() != Code::Ok {
return Err(status);
}
}
true
} else {
false
};
let response = response
.map(|b| decode(codec.decoder(), b).into_stream())
.map(|b| {
if expect_additional_trailers {
future::Either::Left(
decode_response(codec.decoder(), b, status_code).into_stream(),
)
} else {
future::Either::Right(decode_empty(codec.decoder(), b).into_stream())
}
})
.map(Streaming::new);
Ok(Response::from_http(response))
+63 -8
View File
@@ -2,12 +2,52 @@ use crate::{Code, Status};
use bytes::{Buf, BufMut, BytesMut, IntoBuf};
use futures_core::{Stream, TryStream};
use futures_util::future;
// use http::StatusCode;
use http::StatusCode;
use http_body::Body;
use std::pin::Pin;
use tokio_codec::Decoder;
use tracing::{debug, trace};
pub fn decode_request<T, B>(
decoder: T,
source: B,
) -> impl TryStream<Ok = T::Item, Error = Status> + 'static
where
T: Decoder<Error = Status> + 'static,
T::Item: Unpin + 'static,
B: Body + 'static,
B::Error: Into<crate::Error>,
{
decode(decoder, source, Direction::Request)
}
pub fn decode_response<T, B>(
decoder: T,
source: B,
status: StatusCode,
) -> impl TryStream<Ok = T::Item, Error = Status> + 'static
where
T: Decoder<Error = Status> + 'static,
T::Item: Unpin + 'static,
B: Body + 'static,
B::Error: Into<crate::Error>,
{
decode(decoder, source, Direction::Response(status))
}
pub fn decode_empty<T, B>(
decoder: T,
source: B,
) -> impl TryStream<Ok = T::Item, Error = Status> + 'static
where
T: Decoder<Error = Status> + 'static,
T::Item: Unpin + 'static,
B: Body + 'static,
B::Error: Into<crate::Error>,
{
decode(decoder, source, Direction::EmptyResponse)
}
pub struct Streaming<T> {
inner: Pin<Box<dyn Stream<Item = Result<T, Status>> + Send + 'static>>,
}
@@ -34,15 +74,16 @@ enum State {
ReadBody { compression: bool, len: usize },
}
// enum Direction {
// Request,
// Response(StatusCode),
// EmptyResponse,
// }
enum Direction {
Request,
Response(StatusCode),
EmptyResponse,
}
pub fn decode<T, B>(
fn decode<T, B>(
mut decoder: T,
mut source: B,
direction: Direction,
) -> impl TryStream<Ok = T::Item, Error = Status> + 'static
where
T: Decoder<Error = Status> + 'static,
@@ -85,8 +126,22 @@ where
break;
}
}
}
// TODO: poll_trailers for Response status code
if let Direction::Response(status) = direction {
let trailer = future::poll_fn(|cx| unsafe { std::pin::Pin::new_unchecked(&mut source) }.poll_trailers(cx));
let trailer = match trailer.await {
Ok(trailer) => {
crate::status::infer_grpc_status(trailer, status)?;
},
Err(e) => {
let err = e.into();
debug!("decoder inner trailers error: {:?}", err);
let status = Status::from_error(&*err);
Err(status)?;
},
Ok(None) => return,
};
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ mod decode;
mod encode;
mod prost;
pub use self::decode::{decode, Streaming};
pub use self::decode::{decode_empty, decode_request, decode_response, Streaming};
pub use self::encode::encode;
pub use self::prost::ProstCodec;
+1 -1
View File
@@ -1,5 +1,5 @@
#![feature(async_await)]
#![recursion_limit = "256"]
#![recursion_limit = "512"]
//! gRPC implementation
+3 -3
View File
@@ -1,6 +1,6 @@
use crate::{
body::{BoxBody, BytesBuf},
codec::{decode, encode, Codec, Streaming},
codec::{decode_request, encode, Codec, Streaming},
server::{ClientStreamingService, ServerStreamingService, StreamingService, UnaryService},
Code, Request, Response, Status,
};
@@ -132,7 +132,7 @@ where
B::Error: Into<crate::Error> + Send,
{
let (parts, body) = request.into_parts();
let stream = decode(self.codec.decoder(), body).into_stream();
let stream = decode_request(self.codec.decoder(), body).into_stream();
futures_util::pin_mut!(stream);
@@ -154,7 +154,7 @@ where
B::Error: Into<crate::Error> + Send,
{
Request::from_http(
request.map(|b| Streaming::new(decode(self.codec.decoder(), b).into_stream())),
request.map(|b| Streaming::new(decode_request(self.codec.decoder(), b).into_stream())),
)
}