rust_web_server/maintenance/
mod.rs1#[cfg(test)]
22mod tests;
23
24use std::sync::atomic::{AtomicBool, Ordering};
25
26use crate::application::Application;
27use crate::core::New as _;
28use crate::middleware::Middleware;
29use crate::request::Request;
30use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
31use crate::range::Range;
32use crate::mime_type::MimeType;
33use crate::server::ConnectionInfo;
34
35pub static MAINTENANCE_MODE: AtomicBool = AtomicBool::new(false);
37
38fn service_unavailable() -> Response {
39 let mut r = Response::new();
40 r.status_code = *STATUS_CODE_REASON_PHRASE.n503_service_unavailable.status_code;
41 r.reason_phrase = STATUS_CODE_REASON_PHRASE.n503_service_unavailable.reason_phrase.to_string();
42 r.content_range_list = vec![Range::get_content_range(
43 b"Service Temporarily Unavailable".to_vec(),
44 MimeType::TEXT_PLAIN.to_string(),
45 )];
46 r
47}
48
49pub struct MaintenanceLayer;
54
55impl Middleware for MaintenanceLayer {
56 fn accepts_streamed_body(&self, _request: &Request, _connection: &ConnectionInfo) -> bool {
58 true
59 }
60
61
62 fn handle(
63 &self,
64 request: &Request,
65 connection: &ConnectionInfo,
66 next: &dyn Application,
67 ) -> Result<Response, String> {
68 if MAINTENANCE_MODE.load(Ordering::Relaxed) {
69 let path = request.request_uri.split('?').next().unwrap_or(&request.request_uri);
70 if path != "/healthz" && path != "/readyz" {
71 return Ok(service_unavailable());
72 }
73 }
74 next.execute(request, connection)
75 }
76
77 fn runs_inline(&self, _request: &Request, _connection: &ConnectionInfo) -> bool {
79 true
80 }
81
82 fn is_passthrough(&self, _request: &Request, _connection: &ConnectionInfo) -> bool {
86 !MAINTENANCE_MODE.load(Ordering::Relaxed)
87 }
88}