|
1 | | -use bytes::BytesMut; |
2 | 1 | use ext_php_rs::zend::SapiGlobals; |
3 | | -use http_handler::request::Parts; |
4 | | -use http_handler::{ |
5 | | - BodyBuffer, HeaderMap, HeaderName, HeaderValue, Request, ResponseBuilderExt, ResponseLog, |
6 | | - StatusCode, |
7 | | -}; |
| 2 | +use http_handler::{BodyBuffer, Request}; |
8 | 3 | use std::{ffi::c_void, path::PathBuf}; |
9 | 4 |
|
10 | 5 | /// The request context for the PHP SAPI. |
11 | | -/// |
12 | | -/// This has been redesigned to address all issues in FIXME.md: |
13 | | -/// - Uses request Parts to avoid RefUnwindSafe issues (#1) |
14 | | -/// - Stores mutable body for proper consumption (#2) |
15 | | -/// - Uses extension types to accumulate response data (#3, #4) |
16 | | -#[derive(Debug)] |
17 | 6 | pub struct RequestContext { |
18 | | - request_parts: Parts, |
19 | | - request_body: BytesMut, |
20 | | - response_status: StatusCode, |
21 | | - response_headers: HeaderMap, |
22 | | - response_body: BodyBuffer, |
23 | | - response_log: ResponseLog, |
24 | | - response_exception: Option<String>, |
| 7 | + request: Request, |
| 8 | + response_builder: http_handler::response::Builder, |
25 | 9 | docroot: PathBuf, |
26 | 10 | } |
27 | 11 |
|
28 | 12 | impl RequestContext { |
29 | 13 | /// Sets the current request context for the PHP SAPI. |
30 | | - /// |
31 | | - /// Uses into_parts() to avoid RefUnwindSafe issues (FIXME.md #1). |
32 | 14 | pub fn for_request<S>(request: Request, docroot: S) |
33 | 15 | where |
34 | 16 | S: Into<PathBuf>, |
35 | 17 | { |
36 | | - // Use into_parts() to avoid RefUnwindSafe issues (FIXME.md #1) |
37 | | - let (parts, body) = request.into_parts(); |
38 | | - |
39 | 18 | let context = Box::new(RequestContext { |
40 | | - request_parts: parts, |
41 | | - request_body: body, |
42 | | - response_status: StatusCode::OK, |
43 | | - response_headers: HeaderMap::new(), |
44 | | - response_body: BodyBuffer::new(), |
45 | | - response_log: ResponseLog::new(), |
46 | | - response_exception: None, |
| 19 | + request, |
| 20 | + response_builder: http_handler::response::Builder::new(), |
47 | 21 | docroot: docroot.into(), |
48 | 22 | }); |
49 | 23 | let mut globals = SapiGlobals::get_mut(); |
@@ -76,86 +50,32 @@ impl RequestContext { |
76 | 50 | Some(unsafe { Box::from_raw(ptr as *mut RequestContext) }) |
77 | 51 | } |
78 | 52 |
|
79 | | - /// Returns a reference to the request parts. |
80 | | - /// This replaces the old request() method since we now use parts. |
81 | | - pub fn request_parts(&self) -> &Parts { |
82 | | - &self.request_parts |
83 | | - } |
84 | | - |
85 | | - /// Returns a mutable reference to the request body. |
86 | | - /// This allows proper consumption of the body (FIXME.md #2). |
87 | | - pub fn request_body_mut(&mut self) -> &mut BytesMut { |
88 | | - &mut self.request_body |
| 53 | + /// Returns a reference to the request. |
| 54 | + pub fn request(&self) -> &Request { |
| 55 | + &self.request |
89 | 56 | } |
90 | 57 |
|
91 | | - /// Returns a reference to the request body. |
92 | | - pub fn request_body(&self) -> &BytesMut { |
93 | | - &self.request_body |
94 | | - } |
95 | | - |
96 | | - /// Add a header to the response. |
97 | | - pub fn add_response_header<K, V>(&mut self, key: K, value: V) |
98 | | - where |
99 | | - K: TryInto<HeaderName>, |
100 | | - V: TryInto<HeaderValue>, |
101 | | - { |
102 | | - if let (Ok(header_name), Ok(header_value)) = (key.try_into(), value.try_into()) { |
103 | | - self.response_headers.insert(header_name, header_value); |
104 | | - } |
105 | | - } |
106 | | - |
107 | | - /// Set the response status code. |
108 | | - pub fn set_response_status(&mut self, status: u16) { |
109 | | - if let Ok(status_code) = StatusCode::from_u16(status) { |
110 | | - self.response_status = status_code; |
111 | | - } |
| 58 | + /// Returns a mutable reference to the request. |
| 59 | + pub fn request_mut(&mut self) -> &mut Request { |
| 60 | + &mut self.request |
112 | 61 | } |
113 | 62 |
|
114 | | - /// Write data to the response body. |
115 | | - pub fn write_response_body(&mut self, data: &[u8]) { |
116 | | - self.response_body.append(data); |
117 | | - } |
118 | | - |
119 | | - /// Write to the response log. |
120 | | - /// This uses extension types to accumulate log data (FIXME.md #4). |
121 | | - pub fn write_response_log(&mut self, data: &[u8]) { |
122 | | - self.response_log.append(data); |
123 | | - } |
124 | | - |
125 | | - /// Set an exception on the response. |
126 | | - /// This stores the exception to be added via ResponseBuilderExt (FIXME.md #3). |
127 | | - pub fn set_response_exception(&mut self, exception: impl Into<String>) { |
128 | | - self.response_exception = Some(exception.into()); |
| 63 | + /// Returns a mutable reference to the response builder. |
| 64 | + pub fn response_builder_mut(&mut self) -> &mut http_handler::response::Builder { |
| 65 | + &mut self.response_builder |
129 | 66 | } |
130 | 67 |
|
131 | 68 | /// Build the final response using the accumulated data. |
132 | | - /// This properly uses ResponseBuilderExt for logs and exceptions (FIXME.md #3, #4). |
133 | | - pub fn build_response(self) -> Result<http_handler::Response, http_handler::Error> { |
134 | | - // Start building the response |
135 | | - let mut builder = http_handler::response::Response::builder().status(self.response_status); |
136 | | - |
137 | | - // Add all headers |
138 | | - for (key, value) in &self.response_headers { |
139 | | - builder = builder.header(key, value); |
140 | | - } |
141 | | - |
142 | | - // Add extensions using ResponseBuilderExt |
143 | | - builder = builder |
144 | | - .body_buffer(self.response_body) |
145 | | - .log(self.response_log.into_bytes()); |
146 | | - |
147 | | - if let Some(exception) = self.response_exception { |
148 | | - builder = builder.exception(exception); |
149 | | - } |
150 | | - |
151 | | - // Get the body buffer from extensions and build final response |
152 | | - let body = builder |
| 69 | + pub fn build_response(mut self) -> Result<http_handler::Response, http_handler::Error> { |
| 70 | + // Extract the body buffer from extensions (if any was accumulated) |
| 71 | + let body = self |
| 72 | + .response_builder |
153 | 73 | .extensions_mut() |
154 | 74 | .and_then(|ext| ext.remove::<BodyBuffer>()) |
155 | 75 | .unwrap_or_default() |
156 | 76 | .into_bytes_mut(); |
157 | 77 |
|
158 | | - builder.body(body) |
| 78 | + self.response_builder.body(body) |
159 | 79 | } |
160 | 80 |
|
161 | 81 | /// Returns the docroot associated with this request context |
|
0 commit comments