//! ref: composer/src/Composer/Util/Http/Response.php use crate::json::json_file::JsonFile; use indexmap::IndexMap; use shirabe_external_packages::composer::pcre::preg::Preg; use shirabe_php_shim::{LogicException, PhpMixed, preg_quote}; #[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).unwrap_or(false) { // 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 } // TODO(phase-b): historical helpers used in composer_repository — provide stubs. pub fn from_php_mixed(_data: PhpMixed) -> Self { todo!() } pub fn new_fake(_body: Option) -> Self { todo!() } }