Browse Source

feat(rust-volume-server): mirror backend healthz and normalize absolute request targets

codex-rust-volume-server-bootstrap
Chris Lu 4 weeks ago
parent
commit
d6ff6ed6d4
  1. 84
      rust/volume_server/src/main.rs

84
rust/volume_server/src/main.rs

@ -294,6 +294,7 @@ fn start_proxy_listener(
&mut stream,
role,
native_http_config.as_deref(),
&backend_addr,
) {
Ok(true) => return,
Ok(false) => {}
@ -376,6 +377,7 @@ fn try_handle_native_http(
stream: &mut TcpStream,
role: ListenerRole,
config: Option<&NativeHttpConfig>,
backend_http_addr: &str,
) -> io::Result<bool> {
let parsed = match peek_http_request_headers(stream)? {
Some(v) => v,
@ -480,7 +482,12 @@ fn try_handle_native_http(
if parsed.path == "/status" {
write_native_status_response(stream, &parsed.method, parsed.request_id.as_deref())?;
} else {
write_native_healthz_response(stream, &parsed.method, parsed.request_id.as_deref())?;
write_native_healthz_response(
stream,
&parsed.method,
parsed.request_id.as_deref(),
backend_http_addr,
)?;
}
let _ = stream.shutdown(Shutdown::Both);
@ -537,11 +544,7 @@ fn parse_http_request_headers(data: &[u8], header_len: usize) -> Option<ParsedHt
let mut request_parts = request_line.split_whitespace();
let method = request_parts.next()?.to_string();
let raw_path = request_parts.next()?.to_string();
let path = raw_path
.split_once('?')
.map(|(p, _)| p.to_string())
.unwrap_or(raw_path);
let path = normalize_request_path(&raw_path);
let mut request_id = None;
let mut origin = None;
@ -580,6 +583,25 @@ fn is_admin_method_supported(method: &str) -> bool {
)
}
fn normalize_request_path(target: &str) -> String {
let raw = if let Some(rest) = target.strip_prefix("http://") {
rest.split_once('/')
.map(|(_, path)| format!("/{}", path))
.unwrap_or_else(|| "/".to_string())
} else if let Some(rest) = target.strip_prefix("https://") {
rest.split_once('/')
.map(|(_, path)| format!("/{}", path))
.unwrap_or_else(|| "/".to_string())
} else if target.is_empty() {
"/".to_string()
} else {
target.to_string()
};
raw.split_once('?')
.map(|(p, _)| p.to_string())
.unwrap_or(raw)
}
fn is_public_read_method(method: &str) -> bool {
matches!(method, "GET" | "HEAD" | "OPTIONS")
}
@ -615,20 +637,60 @@ fn write_native_status_response(
fn write_native_healthz_response(
stream: &mut TcpStream,
method: &str,
_method: &str,
request_id: Option<&str>,
backend_http_addr: &str,
) -> io::Result<()> {
let body = b"ok\n";
let status = match query_backend_healthz_status(backend_http_addr) {
Some(200) => "200 OK",
Some(503) => "503 Service Unavailable",
Some(code) if (100..=599).contains(&code) => {
return write_native_http_response(
stream,
&format!("{} Unknown", code),
"text/plain; charset=utf-8",
b"",
true,
request_id,
);
}
_ => "503 Service Unavailable",
};
write_native_http_response(
stream,
"200 OK",
status,
"text/plain; charset=utf-8",
body,
method == "HEAD",
b"",
true,
request_id,
)
}
fn query_backend_healthz_status(backend_http_addr: &str) -> Option<u16> {
let mut upstream = TcpStream::connect(backend_http_addr).ok()?;
let _ = upstream.set_read_timeout(Some(Duration::from_millis(500)));
let _ = upstream.set_write_timeout(Some(Duration::from_millis(500)));
let request = format!(
"GET /healthz HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n",
backend_http_addr
);
upstream.write_all(request.as_bytes()).ok()?;
upstream.flush().ok()?;
let mut buf = [0u8; 1024];
let n = upstream.read(&mut buf).ok()?;
if n == 0 {
return None;
}
let line = String::from_utf8_lossy(&buf[..n]);
let status_line = line.lines().next()?;
let mut parts = status_line.split_whitespace();
let _http = parts.next()?;
let code = parts.next()?.parse::<u16>().ok()?;
Some(code)
}
fn write_native_options_response(
stream: &mut TcpStream,
role: ListenerRole,

Loading…
Cancel
Save