Skip to content

Commit 637361a

Browse files
committed
refactor: use foreign-type for request
1 parent 783f68f commit 637361a

File tree

6 files changed

+77
-50
lines changed

6 files changed

+77
-50
lines changed

Cargo.lock

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ targets = []
3939
[dependencies]
4040
allocator-api2 = { version = "0.2.21", default-features = false }
4141
async-task = { version = "4.7.1", optional = true }
42+
foreign-types = "0.5.0"
4243
lock_api = "0.4.13"
4344
nginx-sys = { path = "nginx-sys", version = "0.5.0-beta"}
4445
pin-project-lite = { version = "0.2.16", optional = true }

examples/async.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
44
use std::sync::{Arc, OnceLock};
55
use std::time::Instant;
66

7-
use ngx::core;
7+
use ngx::core::{self, ForeignTypeRef};
88
use ngx::ffi::{
99
ngx_array_push, ngx_command_t, ngx_conf_t, ngx_connection_t, ngx_event_t, ngx_http_handler_pt,
1010
ngx_http_module_t, ngx_http_phases_NGX_HTTP_ACCESS_PHASE, ngx_int_t, ngx_module_t,
@@ -171,7 +171,7 @@ http_request_handler!(async_access_handler, |request: &mut http::Request| {
171171
unsafe { ngx_post_event(&mut ctx.event, addr_of_mut!(ngx_posted_next_events)) };
172172

173173
// Request is no longer needed and can be converted to something movable to the async block
174-
let req = AtomicPtr::new(request.into());
174+
let req = AtomicPtr::new(request.as_ptr());
175175
let done_flag = ctx.done.clone();
176176

177177
let rt = ngx_http_async_runtime();

examples/upstream.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use std::ffi::{c_char, c_void};
1010
use std::mem;
1111

12-
use ngx::core::{Pool, Status};
12+
use ngx::core::{ForeignTypeRef, Pool, Status};
1313
use ngx::ffi::{
1414
ngx_atoi, ngx_command_t, ngx_conf_t, ngx_connection_t, ngx_event_free_peer_pt,
1515
ngx_event_get_peer_pt, ngx_http_module_t, ngx_http_upstream_init_peer_pt,
@@ -133,7 +133,7 @@ http_upstream_init_peer_pt!(
133133
};
134134

135135
let original_init_peer = hccf.original_init_peer.unwrap();
136-
if unsafe { original_init_peer(request.into(), us) != Status::NGX_OK.into() } {
136+
if unsafe { original_init_peer(request.as_ptr(), us) != Status::NGX_OK.into() } {
137137
return Status::NGX_ERROR;
138138
}
139139

src/core/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub use slab::SlabPool;
1010
pub use status::*;
1111
pub use string::*;
1212

13+
pub use foreign_types::ForeignTypeRef;
14+
1315
/// Gets an outer object pointer from a pointer to one of its fields.
1416
/// While there is no corresponding C macro, the pattern is common in the NGINX source.
1517
///

src/http/request.rs

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -89,30 +89,21 @@ macro_rules! http_variable_get {
8989
/// requests.
9090
///
9191
/// See <https://nginx.org/en/docs/dev/development_guide.html#http_request>
92-
#[repr(transparent)]
93-
pub struct Request(ngx_http_request_t);
92+
pub struct Request(foreign_types::Opaque);
9493

95-
impl<'a> From<&'a Request> for *const ngx_http_request_t {
96-
fn from(request: &'a Request) -> Self {
97-
&request.0 as *const _
98-
}
99-
}
100-
101-
impl<'a> From<&'a mut Request> for *mut ngx_http_request_t {
102-
fn from(request: &'a mut Request) -> Self {
103-
&request.0 as *const _ as *mut _
104-
}
94+
unsafe impl foreign_types::ForeignTypeRef for Request {
95+
type CType = ngx_http_request_t;
10596
}
10697

10798
impl AsRef<ngx_http_request_t> for Request {
10899
fn as_ref(&self) -> &ngx_http_request_t {
109-
&self.0
100+
unsafe { &*self.as_ptr() }
110101
}
111102
}
112103

113104
impl AsMut<ngx_http_request_t> for Request {
114105
fn as_mut(&mut self) -> &mut ngx_http_request_t {
115-
&mut self.0
106+
unsafe { &mut *self.as_ptr() }
116107
}
117108
}
118109

@@ -123,20 +114,21 @@ impl Request {
123114
///
124115
/// The caller has provided a valid non-null pointer to a valid `ngx_http_request_t`
125116
/// which shares the same representation as `Request`.
117+
#[inline]
126118
pub unsafe fn from_ngx_http_request<'a>(r: *mut ngx_http_request_t) -> &'a mut Request {
127-
&mut *r.cast::<Request>()
119+
ForeignTypeRef::from_ptr_mut(r)
128120
}
129121

130122
/// Is this the main request (as opposed to a subrequest)?
131123
pub fn is_main(&self) -> bool {
132-
let main = self.0.main.cast();
124+
let main = self.as_ref().main.cast();
133125
core::ptr::eq(self, main)
134126
}
135127

136128
/// Request pool.
137129
pub fn pool(&self) -> Pool {
138130
// SAFETY: This request is allocated from `pool`, thus must be a valid pool.
139-
unsafe { Pool::from_ngx_pool(self.0.pool) }
131+
unsafe { Pool::from_ngx_pool(self.as_ref().pool) }
140132
}
141133

142134
/// Returns the result as an `Option` if it exists, otherwise `None`.
@@ -147,17 +139,17 @@ impl Request {
147139
/// [`ngx_http_upstream_t`] is best described in
148140
/// <https://nginx.org/en/docs/dev/development_guide.html#http_load_balancing>
149141
pub fn upstream(&self) -> Option<*mut ngx_http_upstream_t> {
150-
if self.0.upstream.is_null() {
142+
if self.as_ref().upstream.is_null() {
151143
return None;
152144
}
153-
Some(self.0.upstream)
145+
Some(self.as_ref().upstream)
154146
}
155147

156148
/// Pointer to a [`ngx_connection_t`] client connection object.
157149
///
158150
/// [`ngx_connection_t`]: https://nginx.org/en/docs/dev/development_guide.html#connection
159151
pub fn connection(&self) -> *mut ngx_connection_t {
160-
self.0.connection
152+
self.as_ref().connection
161153
}
162154

163155
/// Pointer to a [`ngx_log_t`].
@@ -169,7 +161,7 @@ impl Request {
169161

170162
/// Get Module context pointer
171163
fn get_module_ctx_ptr(&self, module: &ngx_module_t) -> *mut c_void {
172-
unsafe { *self.0.ctx.add(module.ctx_index) }
164+
unsafe { *self.as_ref().ctx.add(module.ctx_index) }
173165
}
174166

175167
/// Get Module context
@@ -183,9 +175,9 @@ impl Request {
183175
/// Sets the value as the module's context.
184176
///
185177
/// See <https://nginx.org/en/docs/dev/development_guide.html#http_request>
186-
pub fn set_module_ctx(&self, value: *mut c_void, module: &ngx_module_t) {
178+
pub fn set_module_ctx(&mut self, value: *mut c_void, module: &ngx_module_t) {
187179
unsafe {
188-
*self.0.ctx.add(module.ctx_index) = value;
180+
*self.as_mut().ctx.add(module.ctx_index) = value;
189181
};
190182
}
191183

@@ -210,77 +202,81 @@ impl Request {
210202
///
211203
/// [request body]: https://nginx.org/en/docs/dev/development_guide.html#http_request_body
212204
pub fn discard_request_body(&mut self) -> Status {
213-
unsafe { Status(ngx_http_discard_request_body(&mut self.0)) }
205+
unsafe { Status(ngx_http_discard_request_body(self.as_ptr())) }
214206
}
215207

216208
/// Client HTTP [User-Agent].
217209
///
218210
/// [User-Agent]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent
219211
pub fn user_agent(&self) -> Option<&NgxStr> {
220-
if !self.0.headers_in.user_agent.is_null() {
221-
unsafe { Some(NgxStr::from_ngx_str((*self.0.headers_in.user_agent).value)) }
212+
if !self.as_ref().headers_in.user_agent.is_null() {
213+
unsafe {
214+
Some(NgxStr::from_ngx_str(
215+
(*self.as_ref().headers_in.user_agent).value,
216+
))
217+
}
222218
} else {
223219
None
224220
}
225221
}
226222

227223
/// Set HTTP status of response.
228224
pub fn set_status(&mut self, status: HTTPStatus) {
229-
self.0.headers_out.status = status.into();
225+
self.as_mut().headers_out.status = status.into();
230226
}
231227

232228
/// Add header to the `headers_in` object.
233229
///
234230
/// See <https://nginx.org/en/docs/dev/development_guide.html#http_request>
235231
pub fn add_header_in(&mut self, key: &str, value: &str) -> Option<()> {
236232
let table: *mut ngx_table_elt_t =
237-
unsafe { ngx_list_push(&mut self.0.headers_in.headers) as _ };
238-
unsafe { add_to_ngx_table(table, self.0.pool, key, value) }
233+
unsafe { ngx_list_push(&mut self.as_mut().headers_in.headers) as _ };
234+
unsafe { add_to_ngx_table(table, self.as_ref().pool, key, value) }
239235
}
240236

241237
/// Add header to the `headers_out` object.
242238
///
243239
/// See <https://nginx.org/en/docs/dev/development_guide.html#http_request>
244240
pub fn add_header_out(&mut self, key: &str, value: &str) -> Option<()> {
245241
let table: *mut ngx_table_elt_t =
246-
unsafe { ngx_list_push(&mut self.0.headers_out.headers) as _ };
247-
unsafe { add_to_ngx_table(table, self.0.pool, key, value) }
242+
unsafe { ngx_list_push(&mut self.as_mut().headers_out.headers) as _ };
243+
unsafe { add_to_ngx_table(table, self.as_ref().pool, key, value) }
248244
}
249245

250246
/// Set response body [Content-Length].
251247
///
252248
/// [Content-Length]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length
253249
pub fn set_content_length_n(&mut self, n: usize) {
254-
self.0.headers_out.content_length_n = n as off_t;
250+
self.as_mut().headers_out.content_length_n = n as off_t;
255251
}
256252

257253
/// Send the output header.
258254
///
259255
/// Do not call this function until all output headers are set.
260256
pub fn send_header(&mut self) -> Status {
261-
unsafe { Status(ngx_http_send_header(&mut self.0)) }
257+
unsafe { Status(ngx_http_send_header(self.as_ptr())) }
262258
}
263259

264260
/// Flag indicating that the output does not require a body.
265261
///
266262
/// For example, this flag is used by `HTTP HEAD` requests.
267263
pub fn header_only(&self) -> bool {
268-
self.0.header_only() != 0
264+
self.as_ref().header_only() != 0
269265
}
270266

271267
/// request method
272268
pub fn method(&self) -> Method {
273-
Method::from_ngx(self.0.method)
269+
Method::from_ngx(self.as_ref().method)
274270
}
275271

276272
/// path part of request only
277273
pub fn path(&self) -> &NgxStr {
278-
unsafe { NgxStr::from_ngx_str(self.0.uri) }
274+
unsafe { NgxStr::from_ngx_str(self.as_ref().uri) }
279275
}
280276

281277
/// full uri - containing path and args
282278
pub fn unparsed_uri(&self) -> &NgxStr {
283-
unsafe { NgxStr::from_ngx_str(self.0.unparsed_uri) }
279+
unsafe { NgxStr::from_ngx_str(self.as_ref().unparsed_uri) }
284280
}
285281

286282
/// Send the [response body].
@@ -290,13 +286,13 @@ impl Request {
290286
///
291287
/// [response body]: https://nginx.org/en/docs/dev/development_guide.html#http_request_body
292288
pub fn output_filter(&mut self, body: &mut ngx_chain_t) -> Status {
293-
unsafe { Status(ngx_http_output_filter(&mut self.0, body)) }
289+
unsafe { Status(ngx_http_output_filter(self.as_ptr(), body)) }
294290
}
295291

296292
/// Perform internal redirect to a location
297293
pub fn internal_redirect(&self, location: &str) -> Status {
298294
assert!(!location.is_empty(), "uri location is empty");
299-
let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.0.pool, location) as *mut _ };
295+
let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.as_ref().pool, location) as *mut _ };
300296

301297
// FIXME: check status of ngx_http_named_location or ngx_http_internal_redirect
302298
if location.starts_with('@') {
@@ -326,7 +322,7 @@ impl Request {
326322
ngx_int_t,
327323
) -> ngx_int_t,
328324
) -> Status {
329-
let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.0.pool, uri) as *mut _ };
325+
let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.as_ref().pool, uri) as *mut _ };
330326
// -------------
331327
// allocate memory and set values for ngx_http_post_subrequest_t
332328
let sub_ptr = self
@@ -377,13 +373,13 @@ impl Request {
377373
/// Iterate over headers_in
378374
/// each header item is (&str, &str) (borrowed)
379375
pub fn headers_in_iterator(&self) -> NgxListIterator<'_> {
380-
unsafe { list_iterator(&self.0.headers_in.headers) }
376+
unsafe { list_iterator(&self.as_ref().headers_in.headers) }
381377
}
382378

383379
/// Iterate over headers_out
384380
/// each header item is (&str, &str) (borrowed)
385381
pub fn headers_out_iterator(&self) -> NgxListIterator<'_> {
386-
unsafe { list_iterator(&self.0.headers_out.headers) }
382+
unsafe { list_iterator(&self.as_ref().headers_out.headers) }
387383
}
388384
}
389385

@@ -392,21 +388,21 @@ impl crate::http::HttpModuleConfExt for Request {
392388
unsafe fn http_main_conf_unchecked<T>(&self, module: &ngx_module_t) -> Option<NonNull<T>> {
393389
// SAFETY: main_conf[module.ctx_index] is either NULL or allocated with ngx_p(c)alloc and
394390
// explicitly initialized by the module
395-
NonNull::new((*self.0.main_conf.add(module.ctx_index)).cast())
391+
NonNull::new((*self.as_ref().main_conf.add(module.ctx_index)).cast())
396392
}
397393

398394
#[inline]
399395
unsafe fn http_server_conf_unchecked<T>(&self, module: &ngx_module_t) -> Option<NonNull<T>> {
400396
// SAFETY: srv_conf[module.ctx_index] is either NULL or allocated with ngx_p(c)alloc and
401397
// explicitly initialized by the module
402-
NonNull::new((*self.0.srv_conf.add(module.ctx_index)).cast())
398+
NonNull::new((*self.as_ref().srv_conf.add(module.ctx_index)).cast())
403399
}
404400

405401
#[inline]
406402
unsafe fn http_location_conf_unchecked<T>(&self, module: &ngx_module_t) -> Option<NonNull<T>> {
407403
// SAFETY: loc_conf[module.ctx_index] is either NULL or allocated with ngx_p(c)alloc and
408404
// explicitly initialized by the module
409-
NonNull::new((*self.0.loc_conf.add(module.ctx_index)).cast())
405+
NonNull::new((*self.as_ref().loc_conf.add(module.ctx_index)).cast())
410406
}
411407
}
412408

@@ -417,7 +413,7 @@ impl crate::http::HttpModuleConfExt for Request {
417413
impl fmt::Debug for Request {
418414
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419415
f.debug_struct("Request")
420-
.field("request_", &self.0)
416+
.field("request_", &self.as_ref())
421417
.finish()
422418
}
423419
}

0 commit comments

Comments
 (0)