Skip to content

Commit 5019885

Browse files
committed
fix(http2): correctly propagate HTTP2 request cancellation
1 parent 01c03db commit 5019885

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

src/client/dispatch.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use futures::{Async, Poll, Stream};
1+
use futures::{future, Async, Future, Poll, Stream};
22
use futures::sync::{mpsc, oneshot};
33
use want;
44

@@ -202,6 +202,37 @@ impl<T, U> Callback<T, U> {
202202
}
203203
}
204204
}
205+
206+
pub(crate) fn send_when(
207+
self,
208+
mut when: impl Future<Item=U, Error=(::Error, Option<T>)>,
209+
) -> impl Future<Item=(), Error=()> {
210+
let mut cb = Some(self);
211+
212+
// "select" on this callback being canceled, and the future completing
213+
future::poll_fn(move || {
214+
match when.poll() {
215+
Ok(Async::Ready(res)) => {
216+
cb.take()
217+
.expect("polled after complete")
218+
.send(Ok(res));
219+
Ok(().into())
220+
},
221+
Ok(Async::NotReady) => {
222+
// check if the callback is canceled
223+
try_ready!(cb.as_mut().unwrap().poll_cancel());
224+
trace!("send_when canceled");
225+
Ok(().into())
226+
},
227+
Err(err) => {
228+
cb.take()
229+
.expect("polled after complete")
230+
.send(Err(err));
231+
Ok(().into())
232+
}
233+
}
234+
})
235+
}
205236
}
206237

207238
#[cfg(test)]

src/proto/h2/client.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,15 @@ where
163163
let content_length = content_length_parse_all(res.headers());
164164
let res = res.map(|stream|
165165
::Body::h2(stream, content_length));
166-
cb.send(Ok(res));
166+
Ok(res)
167167
},
168168
Err(err) => {
169169
debug!("client response error: {}", err);
170-
cb.send(Err((::Error::new_h2(err), None)));
170+
Err((::Error::new_h2(err), None))
171171
}
172172
}
173-
Ok(())
174173
});
175-
self.executor.execute(fut)?;
174+
self.executor.execute(cb.send_when(fut))?;
176175
continue;
177176
},
178177

0 commit comments

Comments
 (0)