1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use libc::c_void;
use crate::nxt_unit::{
self, nxt_unit_buf_send, nxt_unit_request_info_t, nxt_unit_response_add_content,
nxt_unit_response_add_field, nxt_unit_response_buf_alloc, nxt_unit_response_init,
nxt_unit_response_send,
};
use crate::error::{IntoUnitResult, UnitError, UnitResult};
use crate::request::UnitRequest;
pub struct UnitResponse<'a> {
pub(crate) request: UnitRequest<'a>,
}
impl<'a> std::ops::Deref for UnitResponse<'a> {
type Target = UnitRequest<'a>;
fn deref(&self) -> &Self::Target {
&self.request
}
}
impl UnitResponse<'_> {
pub fn send_buffer<T>(
&mut self,
size: usize,
f: impl FnOnce(&UnitRequest, &mut &mut [u8]) -> UnitResult<T>,
) -> UnitResult<T> {
let req = self.request.nxt_request;
assert!(size <= u32::MAX as usize);
unsafe {
let buf = nxt_unit_response_buf_alloc(req, size as u32);
if buf.is_null() {
return Err(UnitError(nxt_unit::NXT_UNIT_ERROR as i32));
}
libc::memset((*buf).start as *mut c_void, 0, size);
let mut buf_contents = std::slice::from_raw_parts_mut((*buf).start as *mut u8, size);
let result = f(&self.request, &mut buf_contents)?;
(*buf).free = (*buf).free.add(size - buf_contents.len());
nxt_unit_buf_send(buf).into_unit_result()?;
Ok(result)
}
}
}
pub(crate) unsafe fn add_response(
req: *mut nxt_unit_request_info_t,
headers: &[(impl AsRef<[u8]>, impl AsRef<[u8]>)],
body: impl AsRef<[u8]>,
response_size: usize,
) -> UnitResult<()> {
nxt_unit_response_init(req, 200, headers.len() as u32, response_size as u32)
.into_unit_result()?;
for (header_name, header_value) in headers {
nxt_unit_response_add_field(
req,
header_name.as_ref().as_ptr() as *const libc::c_char,
header_name.as_ref().len() as u8,
header_value.as_ref().as_ptr() as *const libc::c_char,
header_value.as_ref().len() as u32,
)
.into_unit_result()?;
}
nxt_unit_response_add_content(
req,
body.as_ref().as_ptr() as *const libc::c_void,
body.as_ref().len() as u32,
)
.into_unit_result()?;
nxt_unit_response_send(req).into_unit_result()?;
Ok(())
}