Skip to content

Commit e5443a6

Browse files
committed
feat: object to manipulate request context
1 parent 5421ae0 commit e5443a6

5 files changed

Lines changed: 151 additions & 170 deletions

File tree

examples/async.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use ngx::ffi::{
1515
ngx_command_t, ngx_conf_t, ngx_connection_t, ngx_event_t, ngx_http_module_t, ngx_int_t,
1616
ngx_module_t, ngx_post_event, ngx_posted_events, ngx_posted_next_events, ngx_str_t, ngx_uint_t,
1717
};
18-
use ngx::http::{self, HttpModule, HttpModuleLocationConf, HttpRequestHandler, MergeConfigError};
18+
use ngx::http::{
19+
self, HttpModule, HttpModuleLocationConf, HttpRequestHandler, MergeConfigError,
20+
RequestWithContext,
21+
};
1922
use ngx::{ngx_conf_log_error, ngx_log_debug_http, ngx_string};
2023
use tokio::runtime::Runtime;
2124

@@ -140,7 +143,7 @@ impl HttpRequestHandler for AsyncAccessHandler {
140143
const PHASE: ngx::http::HttpPhase = ngx::http::HttpPhase::Access;
141144
type Output = Status;
142145

143-
fn handler(request: &mut http::Request) -> Self::Output {
146+
fn handler(mut request: &mut http::Request) -> Self::Output {
144147
let co = Module::location_conf(request).expect("module config is none");
145148

146149
ngx_log_debug_http!(request, "async module enabled: {}", co.enable);
@@ -149,21 +152,23 @@ impl HttpRequestHandler for AsyncAccessHandler {
149152
return Status::NGX_DECLINED;
150153
}
151154

152-
if let Some(ctx) = request.get_module_ctx::<RequestCTX>(Module::module()) {
155+
let rctx: &mut RequestWithContext<Module, RequestCTX>;
156+
(rctx, request) = RequestWithContext::from_request(request);
157+
158+
if let Some(ctx) = rctx.get() {
153159
if !ctx.done.load(Ordering::Relaxed) {
154160
return Status::NGX_AGAIN;
155161
}
156162

157163
return Status::NGX_OK;
158164
}
159165

160-
let ctx = request.pool().allocate(RequestCTX::default());
161-
if ctx.is_null() {
166+
let ctx = rctx.set(RequestCTX::default());
167+
if ctx.is_err() {
162168
return Status::NGX_ERROR;
163169
}
164-
request.set_module_ctx(ctx.cast(), Module::module());
170+
let ctx = ctx.unwrap();
165171

166-
let ctx = unsafe { &mut *ctx };
167172
ctx.event.handler = Some(check_async_work_done);
168173
ctx.event.data = request.connection().cast();
169174
ctx.event.log = unsafe { (*request.connection()).log };

examples/httporigdst.rs

Lines changed: 49 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ngx::ffi::{
88
ngx_http_add_variable, ngx_http_module_t, ngx_http_variable_t, ngx_inet_get_port, ngx_int_t,
99
ngx_module_t, ngx_sock_ntop, ngx_str_t, ngx_variable_value_t, sockaddr, sockaddr_storage,
1010
};
11-
use ngx::http::{self, HttpModule};
11+
use ngx::http::{self, HttpModule, RequestWithContext};
1212
use ngx::{http_variable_get, ngx_log_debug_http, ngx_string};
1313

1414
const IPV4_STRLEN: usize = INET_ADDRSTRLEN as usize;
@@ -196,93 +196,65 @@ unsafe fn ngx_get_origdst(request: &mut http::Request) -> Result<(String, in_por
196196

197197
http_variable_get!(
198198
ngx_http_orig_dst_addr_variable,
199-
|request: &mut http::Request, v: *mut ngx_variable_value_t, _: usize| {
200-
let ctx = request.get_module_ctx::<NgxHttpOrigDstCtx>(Module::module());
201-
if let Some(obj) = ctx {
202-
ngx_log_debug_http!(request, "httporigdst: found context and binding variable",);
203-
unsafe { obj.bind_addr(v) };
204-
return Status::NGX_OK;
205-
}
206-
// lazy initialization:
207-
// get original dest information
208-
// create context
209-
// set context
210-
// bind address
211-
ngx_log_debug_http!(request, "httporigdst: context not found, getting address");
212-
let r = unsafe { ngx_get_origdst(request) };
213-
match r {
214-
Err(e) => {
215-
return e;
199+
|mut request: &mut http::Request, v: *mut ngx_variable_value_t, _: usize| {
200+
let rctx: &mut RequestWithContext<Module, NgxHttpOrigDstCtx>;
201+
(rctx, request) = RequestWithContext::from_request(request);
202+
match rctx.get() {
203+
Some(ctx) => {
204+
ngx_log_debug_http!(request, "httporigdst: found context and binding variable");
205+
unsafe { ctx.bind_addr(v) };
206+
Status::NGX_OK
216207
}
217-
Ok((ip, port)) => {
218-
// create context,
219-
// set context
220-
let new_ctx = request
221-
.pool()
222-
.allocate::<NgxHttpOrigDstCtx>(Default::default());
223-
224-
if new_ctx.is_null() {
225-
return Status::NGX_ERROR;
226-
}
227-
228-
ngx_log_debug_http!(
229-
request,
230-
"httporigdst: saving ip - {:?}, port - {}",
231-
ip,
232-
port,
233-
);
234-
unsafe { (*new_ctx).save(&ip, port, &request.pool()) };
235-
unsafe { (*new_ctx).bind_addr(v) };
236-
request.set_module_ctx(new_ctx as *mut c_void, Module::module());
208+
None => {
209+
ngx_log_debug_http!(request, "httporigdst: context not found, getting address");
210+
unsafe { ngx_get_origdst(request) }.map_or_else(
211+
|e| e,
212+
|(ip, port)| {
213+
rctx.set(NgxHttpOrigDstCtx::default())
214+
.map_or(Status::NGX_ERROR, |ctx| {
215+
unsafe { ctx.bind_addr(v) };
216+
ngx_log_debug_http!(
217+
request,
218+
"httporigdst: saving ip - {ip}, port - {port}",
219+
);
220+
ctx.save(&ip, port, &request.pool())
221+
})
222+
},
223+
)
237224
}
238225
}
239-
Status::NGX_OK
240226
}
241227
);
242228

243229
http_variable_get!(
244230
ngx_http_orig_dst_port_variable,
245-
|request: &mut http::Request, v: *mut ngx_variable_value_t, _: usize| {
246-
let ctx = request.get_module_ctx::<NgxHttpOrigDstCtx>(Module::module());
247-
if let Some(obj) = ctx {
248-
ngx_log_debug_http!(request, "httporigdst: found context and binding variable",);
249-
unsafe { obj.bind_port(v) };
250-
return Status::NGX_OK;
251-
}
252-
// lazy initialization:
253-
// get original dest information
254-
// create context
255-
// set context
256-
// bind port
257-
ngx_log_debug_http!(request, "httporigdst: context not found, getting address");
258-
let r = unsafe { ngx_get_origdst(request) };
259-
match r {
260-
Err(e) => {
261-
return e;
231+
|mut request: &mut http::Request, v: *mut ngx_variable_value_t, _: usize| {
232+
let rctx: &mut RequestWithContext<Module, NgxHttpOrigDstCtx>;
233+
(rctx, request) = RequestWithContext::from_request(request);
234+
match rctx.get() {
235+
Some(ctx) => {
236+
ngx_log_debug_http!(request, "httporigdst: found context and binding variable");
237+
unsafe { ctx.bind_port(v) };
238+
Status::NGX_OK
262239
}
263-
Ok((ip, port)) => {
264-
// create context,
265-
// set context
266-
let new_ctx = request
267-
.pool()
268-
.allocate::<NgxHttpOrigDstCtx>(Default::default());
269-
270-
if new_ctx.is_null() {
271-
return Status::NGX_ERROR;
272-
}
273-
274-
ngx_log_debug_http!(
275-
request,
276-
"httporigdst: saving ip - {:?}, port - {}",
277-
ip,
278-
port,
279-
);
280-
unsafe { (*new_ctx).save(&ip, port, &request.pool()) };
281-
unsafe { (*new_ctx).bind_port(v) };
282-
request.set_module_ctx(new_ctx as *mut c_void, Module::module());
240+
None => {
241+
ngx_log_debug_http!(request, "httporigdst: context not found, getting address");
242+
unsafe { ngx_get_origdst(request) }.map_or_else(
243+
|e| e,
244+
|(ip, port)| {
245+
rctx.set(NgxHttpOrigDstCtx::default())
246+
.map_or(Status::NGX_ERROR, |ctx| {
247+
unsafe { ctx.bind_port(v) };
248+
ngx_log_debug_http!(
249+
request,
250+
"httporigdst: saving ip - {ip}, port - {port}",
251+
);
252+
ctx.save(&ip, port, &request.pool())
253+
})
254+
},
255+
)
283256
}
284257
}
285-
Status::NGX_OK
286258
}
287259
);
288260

src/http/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
mod conf;
22
mod module;
33
mod request;
4+
mod request_context;
45
mod status;
56
mod upstream;
67

78
pub use conf::*;
89
pub use module::*;
910
pub use request::*;
11+
pub use request_context::*;
1012
pub use status::*;

src/http/request.rs

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use core::error;
2-
use core::ffi::c_void;
32
use core::fmt;
43
use core::ptr::NonNull;
54
use core::slice;
@@ -236,28 +235,6 @@ impl Request {
236235
unsafe { (*self.connection()).log }
237236
}
238237

239-
/// Get Module context pointer
240-
fn get_module_ctx_ptr(&self, module: &ngx_module_t) -> *mut c_void {
241-
unsafe { *self.0.ctx.add(module.ctx_index) }
242-
}
243-
244-
/// Get Module context
245-
pub fn get_module_ctx<T>(&self, module: &ngx_module_t) -> Option<&T> {
246-
let ctx = self.get_module_ctx_ptr(module).cast::<T>();
247-
// SAFETY: ctx is either NULL or allocated with ngx_p(c)alloc and
248-
// explicitly initialized by the module
249-
unsafe { ctx.as_ref() }
250-
}
251-
252-
/// Sets the value as the module's context.
253-
///
254-
/// See <https://nginx.org/en/docs/dev/development_guide.html#http_request>
255-
pub fn set_module_ctx(&self, value: *mut c_void, module: &ngx_module_t) {
256-
unsafe {
257-
*self.0.ctx.add(module.ctx_index) = value;
258-
};
259-
}
260-
261238
/// Get the value of a [complex value].
262239
///
263240
/// [complex value]: https://nginx.org/en/docs/dev/development_guide.html#http_complex_values
@@ -384,65 +361,6 @@ impl Request {
384361
Status::NGX_DONE
385362
}
386363

387-
/// Send a subrequest
388-
pub fn subrequest(
389-
&self,
390-
uri: &str,
391-
module: &ngx_module_t,
392-
post_callback: unsafe extern "C" fn(
393-
*mut ngx_http_request_t,
394-
*mut c_void,
395-
ngx_int_t,
396-
) -> ngx_int_t,
397-
) -> Status {
398-
let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.0.pool, uri) as *mut _ };
399-
// -------------
400-
// allocate memory and set values for ngx_http_post_subrequest_t
401-
let sub_ptr = self
402-
.pool()
403-
.alloc(core::mem::size_of::<ngx_http_post_subrequest_t>());
404-
405-
// assert!(sub_ptr.is_null());
406-
let post_subreq =
407-
sub_ptr as *const ngx_http_post_subrequest_t as *mut ngx_http_post_subrequest_t;
408-
unsafe {
409-
(*post_subreq).handler = Some(post_callback);
410-
// WARN: safety! ensure that ctx is already set
411-
(*post_subreq).data = self.get_module_ctx_ptr(module);
412-
}
413-
// -------------
414-
415-
let mut psr: *mut ngx_http_request_t = core::ptr::null_mut();
416-
let r = unsafe {
417-
ngx_http_subrequest(
418-
(self as *const Request as *mut Request).cast(),
419-
uri_ptr,
420-
core::ptr::null_mut(),
421-
&raw mut psr,
422-
sub_ptr as *mut _,
423-
NGX_HTTP_SUBREQUEST_WAITED as _,
424-
)
425-
};
426-
427-
// previously call of ngx_http_subrequest() would ensure that the pointer is not null
428-
// anymore
429-
let sr = unsafe { &mut *psr };
430-
431-
/*
432-
* allocate fake request body to avoid attempts to read it and to make
433-
* sure real body file (if already read) won't be closed by upstream
434-
*/
435-
sr.request_body =
436-
self.pool()
437-
.alloc(core::mem::size_of::<ngx_http_request_body_t>()) as *mut _;
438-
439-
if sr.request_body.is_null() {
440-
return Status::NGX_ERROR;
441-
}
442-
sr.set_header_only(1 as _);
443-
Status(r)
444-
}
445-
446364
/// Iterate over headers_in
447365
/// each header item is (&str, &str) (borrowed)
448366
pub fn headers_in_iterator(&self) -> NgxListIterator<'_> {
@@ -485,10 +403,6 @@ impl crate::http::HttpModuleConfExt for Request {
485403
}
486404
}
487405

488-
// trait OnSubRequestDone {
489-
490-
// }
491-
492406
impl fmt::Debug for Request {
493407
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494408
f.debug_struct("Request")

0 commit comments

Comments
 (0)