Skip to content

Commit de54e57

Browse files
committed
add some comments
1 parent 7161991 commit de54e57

File tree

2 files changed

+27
-12
lines changed

2 files changed

+27
-12
lines changed

src/read_notifier.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@ use async_std::io::{self, BufRead, Read};
66
use async_std::sync::Sender;
77

88
pin_project_lite::pin_project! {
9-
pub(crate) struct ReadNotifier<B>{
9+
/// ReadNotifier forwards [`async_std::io::Read`] and
10+
/// [`async_std::io::BufRead`] to an inner reader. When the
11+
/// ReadNotifier is read from (using `Read`, `ReadExt`, or
12+
/// `BufRead` methods), it sends a single message containing `()`
13+
/// on the channel.
14+
pub(crate) struct ReadNotifier<B> {
1015
#[pin]
1116
reader: B,
1217
sender: Sender<()>,
13-
read: bool
18+
has_been_read: bool
1419
}
1520
}
1621

1722
impl<B> fmt::Debug for ReadNotifier<B> {
1823
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1924
f.debug_struct("ReadNotifier")
20-
.field("read", &self.read)
25+
.field("read", &self.has_been_read)
2126
.finish()
2227
}
2328
}
@@ -27,7 +32,7 @@ impl<B: BufRead> ReadNotifier<B> {
2732
Self {
2833
reader,
2934
sender,
30-
read: false,
35+
has_been_read: false,
3136
}
3237
}
3338
}
@@ -50,9 +55,9 @@ impl<B: Read> Read for ReadNotifier<B> {
5055
) -> Poll<io::Result<usize>> {
5156
let this = self.project();
5257

53-
if !*this.read {
58+
if !*this.has_been_read {
5459
if let Ok(()) = this.sender.try_send(()) {
55-
*this.read = true;
60+
*this.has_been_read = true;
5661
};
5762
}
5863

src/server/decode.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -88,22 +88,32 @@ where
8888
"Unexpected Content-Length header"
8989
);
9090

91-
let (sender, receiver) = sync::channel(1);
91+
// Establish a channel to wait for the body to be read. This
92+
// allows us to avoid sending 100-continue in situations that
93+
// respond without reading the body, saving clients from uploading
94+
// their body.
95+
let (body_read_sender, body_read_receiver) = sync::channel(1);
9296

93-
if let Some(CONTINUE_HEADER_VALUE) = req.header(EXPECT).map(|h| h.as_str()) {
97+
if Some(CONTINUE_HEADER_VALUE) == req.header(EXPECT).map(|h| h.as_str()) {
9498
task::spawn(async move {
95-
if let Ok(()) = receiver.recv().await {
99+
// If the client expects a 100-continue header, spawn a
100+
// task to wait for the first read attempt on the body.
101+
if let Ok(()) = body_read_receiver.recv().await {
96102
io.write_all(CONTINUE_RESPONSE).await.ok();
97103
};
104+
// Since the sender is moved into the Body, this task will
105+
// finish when the client disconnects, whether or not
106+
// 100-continue was sent.
98107
});
99108
}
100109

101110
// Check for Transfer-Encoding
102111
if let Some(encoding) = transfer_encoding {
103112
if encoding.last().as_str() == "chunked" {
104113
let trailer_sender = req.send_trailers();
105-
let reader = BufReader::new(ChunkedDecoder::new(reader, trailer_sender));
106-
let reader = ReadNotifier::new(reader, sender);
114+
let reader = ChunkedDecoder::new(reader, trailer_sender);
115+
let reader = BufReader::new(reader);
116+
let reader = ReadNotifier::new(reader, body_read_sender);
107117
req.set_body(Body::from_reader(reader, None));
108118
return Ok(Some(req));
109119
}
@@ -113,7 +123,7 @@ where
113123
// Check for Content-Length.
114124
if let Some(len) = content_length {
115125
let len = len.last().as_str().parse::<usize>()?;
116-
let reader = ReadNotifier::new(reader.take(len as u64), sender);
126+
let reader = ReadNotifier::new(reader.take(len as u64), body_read_sender);
117127
req.set_body(Body::from_reader(reader, Some(len)));
118128
}
119129

0 commit comments

Comments
 (0)