From b84ba183eb9d571281172c5060726b57a39315a3 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 15 May 2026 01:00:54 +0900 Subject: feat(port): port Response.php --- crates/shirabe/src/util/http/response.rs | 88 ++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'crates/shirabe/src/util/http') diff --git a/crates/shirabe/src/util/http/response.rs b/crates/shirabe/src/util/http/response.rs index 61011cb..ff3af06 100644 --- a/crates/shirabe/src/util/http/response.rs +++ b/crates/shirabe/src/util/http/response.rs @@ -1 +1,89 @@ //! ref: composer/src/Composer/Util/Http/Response.php + +use indexmap::IndexMap; +use shirabe_external_packages::composer::pcre::preg::Preg; +use shirabe_php_shim::{LogicException, PhpMixed, preg_quote}; +use crate::json::json_file::JsonFile; + +#[derive(Debug)] +pub struct Response { + request: IndexMap, + code: i64, + headers: Vec, + body: Option, +} + +impl Response { + pub fn new( + request: IndexMap, + code: Option, + headers: Vec, + body: Option, + ) -> anyhow::Result> { + if !request.contains_key("url") { + return Ok(Err(LogicException { + message: "url key missing from request array".to_string(), + code: 0, + })); + } + Ok(Ok(Self { + request, + code: code.unwrap_or(0), + headers, + body, + })) + } + + pub fn get_status_code(&self) -> i64 { + self.code + } + + pub fn get_status_message(&self) -> Option { + let mut value = None; + for header in &self.headers { + if Preg::is_match(r"(?i)^HTTP/\S+ \d+", header) { + // In case of redirects, headers contain the headers of all responses + // so we can not return directly and need to keep iterating + value = Some(header.clone()); + } + } + value + } + + pub fn get_headers(&self) -> &Vec { + &self.headers + } + + pub fn get_header(&self, name: &str) -> Option { + Self::find_header_value(&self.headers, name) + } + + pub fn get_body(&self) -> Option<&str> { + self.body.as_deref() + } + + pub fn decode_json(&self) -> anyhow::Result { + let url = self.request.get("url") + .and_then(|u| u.as_string()) + .unwrap_or(""); + JsonFile::parse_json(self.body.as_deref(), Some(url)) + } + + pub fn collect(&mut self) { + self.request = IndexMap::new(); + self.code = 0; + self.headers = vec![]; + self.body = None; + } + + pub fn find_header_value(headers: &[String], name: &str) -> Option { + let mut value = None; + let pattern = format!("(?i)^{}:\\s*(.+?)\\s*$", preg_quote(name, None)); + for header in headers { + if let Some(m) = Preg::match_(&pattern, header) { + value = Some(m[1].clone()); + } + } + value + } +} -- cgit v1.3.1