-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(http1): only send
100 Continue
if request body is polled
Before, if a client request included an `Expect: 100-continue` header, the `100 Continue` response was sent immediately. However, this is problematic if the service is going to reply with some 4xx status code and reject the body. This change delays the automatic sending of the `100 Continue` status until the service has call `poll_data` on the request body once.
- Loading branch information
1 parent
a354580
commit c4bb4db
Showing
7 changed files
with
332 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
//! An SPSC broadcast channel. | ||
//! | ||
//! - The value can only be a `usize`. | ||
//! - The consumer is only notified if the value is different. | ||
//! - The value `0` is reserved for closed. | ||
|
||
use futures_util::task::AtomicWaker; | ||
use std::sync::{ | ||
atomic::{AtomicUsize, Ordering}, | ||
Arc, | ||
}; | ||
use std::task; | ||
|
||
type Value = usize; | ||
|
||
pub(crate) const CLOSED: usize = 0; | ||
|
||
pub(crate) fn channel(initial: Value) -> (Sender, Receiver) { | ||
debug_assert!( | ||
initial != CLOSED, | ||
"watch::channel initial state of 0 is reserved" | ||
); | ||
|
||
let shared = Arc::new(Shared { | ||
value: AtomicUsize::new(initial), | ||
waker: AtomicWaker::new(), | ||
}); | ||
|
||
( | ||
Sender { | ||
shared: shared.clone(), | ||
}, | ||
Receiver { shared }, | ||
) | ||
} | ||
|
||
pub(crate) struct Sender { | ||
shared: Arc<Shared>, | ||
} | ||
|
||
pub(crate) struct Receiver { | ||
shared: Arc<Shared>, | ||
} | ||
|
||
struct Shared { | ||
value: AtomicUsize, | ||
waker: AtomicWaker, | ||
} | ||
|
||
impl Sender { | ||
pub(crate) fn send(&mut self, value: Value) { | ||
if self.shared.value.swap(value, Ordering::SeqCst) != value { | ||
self.shared.waker.wake(); | ||
} | ||
} | ||
} | ||
|
||
impl Drop for Sender { | ||
fn drop(&mut self) { | ||
self.send(CLOSED); | ||
} | ||
} | ||
|
||
impl Receiver { | ||
pub(crate) fn load(&mut self, cx: &mut task::Context<'_>) -> Value { | ||
self.shared.waker.register(cx.waker()); | ||
self.shared.value.load(Ordering::SeqCst) | ||
} | ||
|
||
pub(crate) fn peek(&self) -> Value { | ||
self.shared.value.load(Ordering::Relaxed) | ||
} | ||
} |
Oops, something went wrong.