ripht_php_sapi/execution/
result.rs1use super::header::ResponseHeader;
2use super::message::{ExecutionMessage, SyslogLevel};
3
4#[must_use]
9#[derive(Debug, Clone)]
10pub struct ExecutionResult {
11 pub status: u16,
12 pub body: Vec<u8>,
13 pub headers: Vec<ResponseHeader>,
14 pub messages: Vec<ExecutionMessage>,
15}
16
17impl ExecutionResult {
18 pub fn body_string(&self) -> String {
19 String::from_utf8_lossy(&self.body).into_owned()
20 }
21
22 pub fn body_str(&self) -> Result<&str, std::str::Utf8Error> {
23 std::str::from_utf8(&self.body)
24 }
25
26 pub fn status_code(&self) -> u16 {
27 self.status
28 }
29
30 pub fn has_errors(&self) -> bool {
31 self.messages
32 .iter()
33 .any(|m| m.is_error())
34 }
35
36 pub fn has_warnings(&self) -> bool {
37 self.messages
38 .iter()
39 .any(|m| m.is_error() || m.level == SyslogLevel::Warning)
40 }
41
42 pub fn errors(&self) -> impl Iterator<Item = &ExecutionMessage> {
43 self.messages
44 .iter()
45 .filter(|m| m.is_error())
46 }
47
48 pub fn all_messages(&self) -> impl Iterator<Item = &ExecutionMessage> {
49 self.messages.iter()
50 }
51
52 pub fn header(&self, name: &str) -> Option<&str> {
53 self.headers
54 .iter()
55 .find(|h| {
56 h.name()
57 .eq_ignore_ascii_case(name)
58 })
59 .map(|h| h.value())
60 }
61
62 pub fn headers_all(&self, name: &str) -> Vec<&str> {
63 self.headers
64 .iter()
65 .filter(|h| {
66 h.name()
67 .eq_ignore_ascii_case(name)
68 })
69 .map(|h| h.value())
70 .collect()
71 }
72
73 pub fn is_success(&self) -> bool {
74 (200..300).contains(&self.status)
75 }
76
77 pub fn is_redirect(&self) -> bool {
78 (300..400).contains(&self.status)
79 }
80
81 pub fn is_client_error(&self) -> bool {
82 (400..500).contains(&self.status)
83 }
84
85 pub fn is_server_error(&self) -> bool {
86 (500..600).contains(&self.status)
87 }
88}
89
90impl Default for ExecutionResult {
91 fn default() -> Self {
92 Self {
93 status: 200,
94 body: Vec::new(),
95 headers: Vec::new(),
96 messages: Vec::new(),
97 }
98 }
99}
100
101#[cfg(feature = "http")]
102impl ExecutionResult {
103 pub fn into_http_response(self) -> http::Response<Vec<u8>> {
104 let mut builder = http::Response::builder().status(self.status);
105
106 for h in &self.headers {
107 builder = builder.header(h.name(), h.value());
108 }
109
110 builder
111 .body(self.body)
112 .unwrap_or_else(|_| http::Response::new(Vec::new()))
113 }
114}
115
116#[cfg(feature = "http")]
117impl From<ExecutionResult> for http::Response<Vec<u8>> {
118 fn from(res: ExecutionResult) -> Self {
119 res.into_http_response()
120 }
121}