1use std::io::Read;
2use std::marker::PhantomData;
3
4use libc::c_void;
5
6use crate::error::{IntoUnitResult, UnitResult};
7use crate::nxt_unit::{self, nxt_unit_request_info_t, nxt_unit_sptr_get, nxt_unit_sptr_t};
8use crate::response::Response;
9use crate::{BodyWriter, UnitError};
10
11pub struct Request<'a> {
16 pub(crate) nxt_request: *mut nxt_unit_request_info_t,
17 pub(crate) _lifetime: PhantomData<&'a mut ()>,
18}
19
20impl<'a> Request<'a> {
21 pub fn create_response(
31 &'a self,
32 status_code: u16,
33 max_fields_count: usize,
34 max_response_size: usize,
35 ) -> UnitResult<Response<'a>> {
36 unsafe {
41 nxt_unit::nxt_unit_response_init(
42 self.nxt_request,
43 status_code,
44 max_fields_count as u32,
45 max_response_size as u32,
46 )
47 .into_unit_result()?;
48 }
49
50 Ok(Response { request: self })
51 }
52
53 pub fn send_response(
63 &self,
64 status_code: u16,
65 headers: &[(impl AsRef<[u8]>, impl AsRef<[u8]>)],
66 body: impl AsRef<[u8]>,
67 ) -> UnitResult<()> {
68 let headers_size: usize = headers
69 .iter()
70 .map(|(name, value)| name.as_ref().len() + value.as_ref().len())
71 .sum();
72 let response_size = headers_size + body.as_ref().len();
73
74 for (name, value) in headers {
75 assert!(name.as_ref().len() <= u8::MAX as usize);
76 assert!(value.as_ref().len() <= u32::MAX as usize);
77 }
78
79 let response = self.create_response(status_code, headers.len(), response_size)?;
80 for (name, value) in headers {
81 response.add_field(name, value)?;
82 }
83 response.add_content(body)?;
84 response.send()
85 }
86
87 pub fn write_chunks(&'a self, chunk_size: usize) -> std::io::Result<BodyWriter<'a>> {
101 BodyWriter::new(self, chunk_size)
102 }
103
104 pub fn send_chunks_with_writer<T>(
113 &'a self,
114 chunk_size: usize,
115 f: impl FnOnce(&mut BodyWriter<'a>) -> std::io::Result<T>,
116 ) -> UnitResult<T> {
117 let write = || -> std::io::Result<T> {
118 let mut writer = self.write_chunks(chunk_size)?;
119 let result = f(&mut writer)?;
120 std::io::Write::flush(&mut writer)?;
121 Ok(result)
122 };
123
124 write().map_err(|err| {
125 self.log(
126 LogLevel::Error,
127 &format!("Error writing to response: {}", err),
128 );
129 UnitError::error()
130 })
131 }
132
133 pub fn send_chunk_with_buffer<T>(
144 &self,
145 size: usize,
146 f: impl FnOnce(&mut &mut [u8]) -> UnitResult<T>,
147 ) -> UnitResult<T> {
148 let req = self.nxt_request;
149
150 assert!(size <= u32::MAX as usize);
151
152 unsafe {
153 let buf = nxt_unit::nxt_unit_response_buf_alloc(req, size as u32);
154
155 if buf.is_null() {
156 return Err(UnitError(nxt_unit::NXT_UNIT_ERROR as i32));
157 }
158
159 libc::memset((*buf).start as *mut c_void, 0, size);
160
161 let mut buf_contents = std::slice::from_raw_parts_mut((*buf).start as *mut u8, size);
162 let result = f(&mut buf_contents)?;
163
164 (*buf).free = (*buf).free.add(size - buf_contents.len());
165
166 nxt_unit::nxt_unit_buf_send(buf).into_unit_result()?;
167
168 Ok(result)
169 }
170 }
171
172 pub fn read_body(&self, target: &mut [u8]) -> usize {
178 unsafe {
179 let bytes = nxt_unit::nxt_unit_request_read(
180 self.nxt_request,
181 target.as_mut_ptr() as *mut c_void,
182 target.len() as u64,
183 );
184 bytes as usize
185 }
186 }
187
188 pub fn body(&self) -> BodyReader<'a> {
191 BodyReader {
192 _lifetime: Default::default(),
193 nxt_request: self.nxt_request,
194 }
195 }
196
197 pub fn fields(&self) -> impl Iterator<Item = (&str, &str)> {
199 unsafe {
200 let r = &(*(*self.nxt_request).request);
201
202 (0..r.fields_count as isize).into_iter().map(|i| {
203 let field = &*r.fields.as_ptr().offset(i);
204 let name = sptr_to_slice(&field.name, field.name_length.into());
205 let value = sptr_to_slice(&field.value, field.value_length.into());
206 (name, value)
207 })
208 }
209 }
210
211 pub fn tls(&self) -> bool {
213 unsafe { (*(*self.nxt_request).request).tls != 0 }
214 }
215
216 pub fn method(&self) -> &str {
218 unsafe {
219 let r = &(*(*self.nxt_request).request);
220 sptr_to_slice(&r.method, r.method_length.into())
221 }
222 }
223
224 pub fn version(&self) -> &str {
226 unsafe {
227 let r = &(*(*self.nxt_request).request);
228 sptr_to_slice(&r.version, r.version_length.into())
229 }
230 }
231
232 pub fn remote(&self) -> &str {
234 unsafe {
235 let r = &(*(*self.nxt_request).request);
236 sptr_to_slice(&r.remote, r.remote_length.into())
237 }
238 }
239
240 pub fn local(&self) -> &str {
242 unsafe {
243 let r = &(*(*self.nxt_request).request);
244 sptr_to_slice(&r.local, r.local_length.into())
245 }
246 }
247
248 pub fn server_name(&self) -> &str {
250 unsafe {
251 let r = &(*(*self.nxt_request).request);
252 sptr_to_slice(&r.server_name, r.server_name_length)
253 }
254 }
255
256 pub fn target(&self) -> &str {
258 unsafe {
259 let r = &(*(*self.nxt_request).request);
260 sptr_to_slice(&r.target, r.target_length)
261 }
262 }
263
264 pub fn path(&self) -> &str {
266 unsafe {
267 let r = &(*(*self.nxt_request).request);
268 sptr_to_slice(&r.path, r.path_length)
269 }
270 }
271
272 pub fn query(&self) -> &str {
274 unsafe {
275 let r = &(*(*self.nxt_request).request);
276 sptr_to_slice(&r.query, r.query_length)
277 }
278 }
279
280 pub fn log<S: AsRef<str>>(&self, level: LogLevel, message: S) {
282 unsafe {
283 nxt_unit::nxt_unit_req_log(
284 self.nxt_request,
285 level as i32,
286 "%s\0".as_ptr() as *const i8,
287 message.as_ref(),
288 )
289 }
290 }
291}
292
293unsafe fn sptr_to_slice(sptr: &nxt_unit_sptr_t, length: u32) -> &str {
294 let ptr = nxt_unit_sptr_get(sptr) as *mut u8;
295 let slice = std::slice::from_raw_parts(ptr, length as usize);
296 std::str::from_utf8(slice).unwrap()
298}
299
300#[repr(u32)]
301pub enum LogLevel {
302 Alert = nxt_unit::NXT_UNIT_LOG_ALERT,
303 Error = nxt_unit::NXT_UNIT_LOG_ERR,
304 Warning = nxt_unit::NXT_UNIT_LOG_WARN,
305 Notice = nxt_unit::NXT_UNIT_LOG_NOTICE,
306 Info = nxt_unit::NXT_UNIT_LOG_INFO,
307 Debug = nxt_unit::NXT_UNIT_LOG_DEBUG,
308}
309
310pub struct BodyReader<'a> {
315 _lifetime: std::marker::PhantomData<&'a ()>,
316 nxt_request: *mut nxt_unit_request_info_t,
317}
318
319impl BodyReader<'_> {
320 pub fn read_to_vec(&mut self) -> std::io::Result<Vec<u8>> {
323 let mut vec = Vec::new();
324 self.read_to_end(&mut vec)?;
325 Ok(vec)
326 }
327}
328
329impl std::panic::UnwindSafe for BodyReader<'_> {}
330
331impl std::io::Read for BodyReader<'_> {
332 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
333 let bytes = unsafe {
338 nxt_unit::nxt_unit_request_read(
339 self.nxt_request,
340 buf.as_mut_ptr() as *mut c_void,
341 buf.len() as u64,
342 )
343 };
344 Ok(bytes as usize)
345 }
346}