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.
This commit is contained in:
		| @@ -14,6 +14,7 @@ pub(crate) mod io; | ||||
| mod lazy; | ||||
| mod never; | ||||
| pub(crate) mod task; | ||||
| pub(crate) mod watch; | ||||
|  | ||||
| pub use self::exec::Executor; | ||||
| pub(crate) use self::exec::{BoxSendFuture, Exec}; | ||||
|   | ||||
							
								
								
									
										73
									
								
								src/common/watch.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/common/watch.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user