From d20e759a7e66527d35110e11f7651a5cfee86161 Mon Sep 17 00:00:00 2001 From: Eloi DEMOLIS Date: Mon, 18 Mar 2024 17:11:11 +0100 Subject: [PATCH] Fix some timeout edge cases - Explicitely use the frontend timeout on keep-alive (may introduce a specific one later) - Put timeout responsibility on the backend whenever we read the first bytes - Mark as terminated GET requests with no length (we assume no body) - Properly reset the HttpContext of the session Signed-off-by: Eloi DEMOLIS --- bin/src/util.rs | 1 - lib/src/protocol/kawa_h1/editor.rs | 16 ++++++++++++++++ lib/src/protocol/kawa_h1/mod.rs | 25 ++++++++++++++++++------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/bin/src/util.rs b/bin/src/util.rs index a3ae645bd..7b322eb33 100644 --- a/bin/src/util.rs +++ b/bin/src/util.rs @@ -162,7 +162,6 @@ pub unsafe fn get_executable_path() -> Result { Ok(path_str) } - #[cfg(target_os = "macos")] extern "C" { pub fn _NSGetExecutablePath(buf: *mut libc::c_char, size: *mut u32) -> i32; diff --git a/lib/src/protocol/kawa_h1/editor.rs b/lib/src/protocol/kawa_h1/editor.rs index 177a86c74..d1e4a884f 100644 --- a/lib/src/protocol/kawa_h1/editor.rs +++ b/lib/src/protocol/kawa_h1/editor.rs @@ -95,6 +95,10 @@ impl HttpContext { .map(ToOwned::to_owned); } + if self.method == Some(Method::Get) && request.body_size == kawa::BodySize::Empty { + request.parsing_phase = kawa::ParsingPhase::Terminated; + } + let public_ip = self.public_address.ip(); let public_port = self.public_address.port(); let proto = match self.protocol { @@ -337,4 +341,16 @@ impl HttpContext { val: kawa::Store::from_string(self.id.to_string()), })); } + + pub fn reset(&mut self) { + self.keep_alive_backend = true; + self.keep_alive_frontend = true; + self.sticky_session_found = None; + self.method = None; + self.authority = None; + self.path = None; + self.status = None; + self.reason = None; + self.user_agent = None; + } } diff --git a/lib/src/protocol/kawa_h1/mod.rs b/lib/src/protocol/kawa_h1/mod.rs index d41ca6930..8062abbff 100644 --- a/lib/src/protocol/kawa_h1/mod.rs +++ b/lib/src/protocol/kawa_h1/mod.rs @@ -222,10 +222,8 @@ impl Http Http Http { debug!("{} keep alive front/back", self.log_context()); @@ -636,6 +635,12 @@ impl Http SessionState if self.frontend_token == token { self.container_frontend_timeout.triggered(); return match self.timeout_status() { + // we do not have a complete answer TimeoutStatus::Request => { self.set_answer(DefaultAnswerStatus::Answer408, None); self.writable(metrics) } + // we have a complete answer but the response did not start TimeoutStatus::WaitingForResponse => { - self.set_answer(DefaultAnswerStatus::Answer504, None); + self.set_answer(DefaultAnswerStatus::Answer408, None); self.writable(metrics) } - TimeoutStatus::Response => StateResult::CloseSession, + // we have a complete answer and the start of a response, but the request was not tagged as terminated + // for now we place responsibility of timeout on the backend in those cases, so we ignore this + TimeoutStatus::Response => StateResult::Continue, + // timeout in keep-alive, simply close the connection TimeoutStatus::WaitingForNewRequest => StateResult::CloseSession, }; } @@ -1796,6 +1806,7 @@ impl SessionState ); StateResult::CloseSession } + // in keep-alive, we place responsibility of timeout on the frontend, so we ignore this TimeoutStatus::WaitingForNewRequest => StateResult::Continue, }; }