From 87378b434257afe0d4ffb4093eafa6282e0d2ec8 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 2 Aug 2026 17:33:02 +0900 Subject: feat(php-shim): implement HTTP last-response-headers store and ASCII mb_check_encoding http_get_last_response_headers()/http_clear_last_response_headers() now back a thread-local store with a recording hook for the (still unported) HTTP stream layer; with no request recorded they return None, matching PHP. mb_check_encoding gains the trivial ASCII arm; other encodings still need the mbstring tables and stay todo!(). Co-Authored-By: Claude Fable 5 --- crates/shirabe-php-shim/src/net.rs | 21 +++++++++++++++++++-- crates/shirabe-php-shim/src/string.rs | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/shirabe-php-shim/src/net.rs b/crates/shirabe-php-shim/src/net.rs index 5632c83e..605ee019 100644 --- a/crates/shirabe-php-shim/src/net.rs +++ b/crates/shirabe-php-shim/src/net.rs @@ -35,10 +35,27 @@ pub fn inet_pton(host: &str) -> Option> { } } +thread_local! { + // PHP records the response headers of the most recent HTTP stream wrapper request + // (the engine-side storage behind `$http_response_header` and, since PHP 8.4, the + // http_get_last_response_headers()/http_clear_last_response_headers() pair). + static LAST_RESPONSE_HEADERS: std::cell::RefCell>> = + const { std::cell::RefCell::new(None) }; +} + +// Engine-side hook with no PHP userland counterpart: the HTTP stream layer must call this +// after each request, like PHP's http wrapper populating `$http_response_header`. No stream +// layer performs HTTP requests yet (see the TODO(phase-c) in util/remote_filesystem.rs), so +// until then the store stays empty and the getter below returns None, which matches PHP +// before any HTTP stream request was made. +pub fn http_record_last_response_headers(headers: Vec) { + LAST_RESPONSE_HEADERS.with(|h| *h.borrow_mut() = Some(headers)); +} + pub fn http_get_last_response_headers() -> Option> { - todo!() + LAST_RESPONSE_HEADERS.with(|h| h.borrow().clone()) } pub fn http_clear_last_response_headers() { - todo!() + LAST_RESPONSE_HEADERS.with(|h| *h.borrow_mut() = None); } diff --git a/crates/shirabe-php-shim/src/string.rs b/crates/shirabe-php-shim/src/string.rs index d793082d..fcf7baf2 100644 --- a/crates/shirabe-php-shim/src/string.rs +++ b/crates/shirabe-php-shim/src/string.rs @@ -369,6 +369,8 @@ pub fn mb_check_encoding(_value: &str, _encoding: &str) -> bool { match _encoding.to_ascii_uppercase().replace('-', "").as_str() { // A Rust &str is, by construction, valid UTF-8. "UTF8" => true, + "ASCII" | "USASCII" => _value.is_ascii(), + // Other encodings need the mbstring validation tables, which have not been ported. _ => todo!(), } } -- cgit v1.3.1