Skip to content

Commit ac84af6

Browse files
authored
feat(http1): add support for receiving trailer fields (#3637)
This allows receiving HTTP/1 chunked trailers, both as a client and as a server. The number of trailer pairs is limited to 1024. The size of the trailer fields is limited. The limit accounts for a single, very large trailer field or many trailer fields that exceed the limit in aggregate. Closes #2703
1 parent e77cefe commit ac84af6

File tree

7 files changed

+661
-80
lines changed

7 files changed

+661
-80
lines changed

src/body/incoming.rs

+13
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,19 @@ impl Sender {
410410
.map_err(|err| err.into_inner().expect("just sent Ok"))
411411
}
412412

413+
#[cfg(feature = "http1")]
414+
pub(crate) fn try_send_trailers(
415+
&mut self,
416+
trailers: HeaderMap,
417+
) -> Result<(), Option<HeaderMap>> {
418+
let tx = match self.trailers_tx.take() {
419+
Some(tx) => tx,
420+
None => return Err(None),
421+
};
422+
423+
tx.send(trailers).map_err(|err| Some(err))
424+
}
425+
413426
#[cfg(test)]
414427
pub(crate) fn abort(mut self) {
415428
self.send_error(crate::Error::new_body_write_aborted());

src/proto/h1/conn.rs

+42-23
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use bytes::{Buf, Bytes};
1111
use futures_util::ready;
1212
use http::header::{HeaderValue, CONNECTION, TE};
1313
use http::{HeaderMap, Method, Version};
14+
use http_body::Frame;
1415
use httparse::ParserConfig;
1516

1617
use super::io::Buffered;
@@ -268,10 +269,20 @@ where
268269
self.try_keep_alive(cx);
269270
}
270271
} else if msg.expect_continue && msg.head.version.gt(&Version::HTTP_10) {
271-
self.state.reading = Reading::Continue(Decoder::new(msg.decode));
272+
let h1_max_header_size = None; // TODO: remove this when we land h1_max_header_size support
273+
self.state.reading = Reading::Continue(Decoder::new(
274+
msg.decode,
275+
self.state.h1_max_headers,
276+
h1_max_header_size,
277+
));
272278
wants = wants.add(Wants::EXPECT);
273279
} else {
274-
self.state.reading = Reading::Body(Decoder::new(msg.decode));
280+
let h1_max_header_size = None; // TODO: remove this when we land h1_max_header_size support
281+
self.state.reading = Reading::Body(Decoder::new(
282+
msg.decode,
283+
self.state.h1_max_headers,
284+
h1_max_header_size,
285+
));
275286
}
276287

277288
self.state.allow_trailer_fields = msg
@@ -312,33 +323,41 @@ where
312323
pub(crate) fn poll_read_body(
313324
&mut self,
314325
cx: &mut Context<'_>,
315-
) -> Poll<Option<io::Result<Bytes>>> {
326+
) -> Poll<Option<io::Result<Frame<Bytes>>>> {
316327
debug_assert!(self.can_read_body());
317328

318329
let (reading, ret) = match self.state.reading {
319330
Reading::Body(ref mut decoder) => {
320331
match ready!(decoder.decode(cx, &mut self.io)) {
321-
Ok(slice) => {
322-
let (reading, chunk) = if decoder.is_eof() {
323-
debug!("incoming body completed");
324-
(
325-
Reading::KeepAlive,
326-
if !slice.is_empty() {
327-
Some(Ok(slice))
328-
} else {
329-
None
330-
},
331-
)
332-
} else if slice.is_empty() {
333-
error!("incoming body unexpectedly ended");
334-
// This should be unreachable, since all 3 decoders
335-
// either set eof=true or return an Err when reading
336-
// an empty slice...
337-
(Reading::Closed, None)
332+
Ok(frame) => {
333+
if frame.is_data() {
334+
let slice = frame.data_ref().unwrap_or_else(|| unreachable!());
335+
let (reading, maybe_frame) = if decoder.is_eof() {
336+
debug!("incoming body completed");
337+
(
338+
Reading::KeepAlive,
339+
if !slice.is_empty() {
340+
Some(Ok(frame))
341+
} else {
342+
None
343+
},
344+
)
345+
} else if slice.is_empty() {
346+
error!("incoming body unexpectedly ended");
347+
// This should be unreachable, since all 3 decoders
348+
// either set eof=true or return an Err when reading
349+
// an empty slice...
350+
(Reading::Closed, None)
351+
} else {
352+
return Poll::Ready(Some(Ok(frame)));
353+
};
354+
(reading, Poll::Ready(maybe_frame))
355+
} else if frame.is_trailers() {
356+
(Reading::Closed, Poll::Ready(Some(Ok(frame))))
338357
} else {
339-
return Poll::Ready(Some(Ok(slice)));
340-
};
341-
(reading, Poll::Ready(chunk))
358+
trace!("discarding unknown frame");
359+
(Reading::Closed, Poll::Ready(None))
360+
}
342361
}
343362
Err(e) => {
344363
debug!("incoming body decode error: {}", e);

0 commit comments

Comments
 (0)