Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions crates/lang_handler/src/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
ffi,
ffi::{c_char, CStr, CString},
ffi::{self, c_char, CStr, CString},
net::SocketAddr,
};

use bytes::{Buf, BufMut};
Expand Down Expand Up @@ -216,6 +216,20 @@ impl From<&lh_request_t> for Request {
}
}

fn c_char_to_socket_addr(value: *const ffi::c_char) -> Option<SocketAddr> {
if value.is_null() {
return None;
}

// Convert to &str
let value = match unsafe { CStr::from_ptr(value) }.to_str() {
Err(_) => return None,
Ok(s) => s,
};

value.parse::<SocketAddr>().ok()
}

/// Create a new `lh_request_t`.
///
/// # Examples
Expand All @@ -229,6 +243,8 @@ pub extern "C" fn lh_request_new(
url: *const ffi::c_char,
headers: *mut lh_headers_t,
body: *const ffi::c_char,
local_socket: *const ffi::c_char,
remote_socket: *const ffi::c_char,
) -> *mut lh_request_t {
let method = unsafe { CStr::from_ptr(method).to_string_lossy().into_owned() };
let url_str = unsafe { CStr::from_ptr(url).to_string_lossy().into_owned() };
Expand All @@ -238,8 +254,17 @@ pub extern "C" fn lh_request_new(
} else {
Some(unsafe { CStr::from_ptr(body).to_bytes() })
};
let local_socket = c_char_to_socket_addr(local_socket);
let remote_socket = c_char_to_socket_addr(remote_socket);
let headers = unsafe { &*headers };
let request = Request::new(method, url, headers.into(), body.unwrap_or(&[]));
let request = Request::new(
method,
url,
headers.into(),
body.unwrap_or(&[]),
local_socket,
remote_socket,
);
Box::into_raw(Box::new(request.into()))
}

Expand Down
142 changes: 135 additions & 7 deletions crates/lang_handler/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::fmt::Debug;
use std::{
fmt::Debug,
net::{AddrParseError, SocketAddr},
};

use bytes::{Bytes, BytesMut};
use url::{ParseError, Url};
Expand Down Expand Up @@ -37,6 +40,8 @@ pub struct Request {
headers: Headers,
// TODO: Support Stream bodies when napi.rs supports it
body: Bytes,
local_socket: Option<SocketAddr>,
remote_socket: Option<SocketAddr>,
}

unsafe impl Sync for Request {}
Expand All @@ -57,14 +62,25 @@ impl Request {
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// headers,
/// "Hello, World!"
/// "Hello, World!",
/// None,
/// None,
/// );
pub fn new<T: Into<Bytes>>(method: String, url: Url, headers: Headers, body: T) -> Self {
pub fn new<T: Into<Bytes>>(
method: String,
url: Url,
headers: Headers,
body: T,
local_socket: Option<SocketAddr>,
remote_socket: Option<SocketAddr>,
) -> Self {
Self {
method,
url,
headers,
body: body.into(),
local_socket,
remote_socket,
}
}

Expand Down Expand Up @@ -133,7 +149,9 @@ impl Request {
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// Headers::new(),
/// "Hello, World!"
/// "Hello, World!",
/// None,
/// None,
/// );
///
/// assert_eq!(request.method(), "POST");
Expand All @@ -153,7 +171,9 @@ impl Request {
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// Headers::new(),
/// "Hello, World!"
/// "Hello, World!",
/// None,
/// None,
/// );
///
/// assert_eq!(request.url().as_str(), "http://example.com/test.php");
Expand All @@ -176,7 +196,9 @@ impl Request {
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// headers,
/// "Hello, World!"
/// "Hello, World!",
/// None,
/// None,
/// );
///
/// assert_eq!(request.headers().get("Accept"), Some(&vec!["text/html".to_string()]));
Expand All @@ -196,14 +218,60 @@ impl Request {
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// Headers::new(),
/// "Hello, World!"
/// "Hello, World!",
/// None,
/// None,
/// );
///
/// assert_eq!(request.body(), "Hello, World!");
/// ```
pub fn body(&self) -> Bytes {
self.body.clone()
}

/// Returns the local socket address of the request.
///
/// # Examples
///
/// ```
/// use lang_handler::{Request, Headers};
///
/// let request = Request::new(
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// Headers::new(),
/// "Hello, World!",
/// None,
/// None,
/// );
///
/// assert_eq!(request.local_socket(), None);
/// ```
pub fn local_socket(&self) -> Option<SocketAddr> {
self.local_socket
}

/// Returns the remote socket address of the request.
///
/// # Examples
///
/// ```
/// use lang_handler::{Request, Headers};
///
/// let request = Request::new(
/// "POST".to_string(),
/// "http://example.com/test.php".parse().unwrap(),
/// Headers::new(),
/// "Hello, World!",
/// None,
/// None,
/// );
///
/// assert_eq!(request.remote_socket(), None);
/// ```
pub fn remote_socket(&self) -> Option<SocketAddr> {
self.remote_socket
}
}

/// Builds an HTTP request.
Expand Down Expand Up @@ -233,6 +301,8 @@ pub struct RequestBuilder {
url: Option<Url>,
headers: Headers,
body: BytesMut,
local_socket: Option<SocketAddr>,
remote_socket: Option<SocketAddr>,
}

impl RequestBuilder {
Expand All @@ -251,6 +321,8 @@ impl RequestBuilder {
url: None,
headers: Headers::new(),
body: BytesMut::with_capacity(1024),
local_socket: None,
remote_socket: None,
}
}

Expand Down Expand Up @@ -285,6 +357,8 @@ impl RequestBuilder {
url: Some(request.url().clone()),
headers: request.headers().clone(),
body: BytesMut::from(request.body()),
local_socket: request.local_socket.clone(),
remote_socket: request.remote_socket.clone(),
}
}

Expand Down Expand Up @@ -372,6 +446,58 @@ impl RequestBuilder {
self
}

/// Sets the local socket of the request.
///
/// # Examples
///
/// ```
/// use lang_handler::RequestBuilder;
///
/// let request = RequestBuilder::new()
/// .local_socket("127.0.0.1:8080").expect("invalid local socket")
/// .build();
///
/// assert_eq!(request.local_socket(), "127.0.0.1:8080");
/// ```
pub fn local_socket<T>(mut self, local_socket: T) -> Result<Self, AddrParseError>
where
T: Into<String>,
{
match local_socket.into().parse() {
Err(e) => Err(e),
Ok(local_socket) => {
self.local_socket = Some(local_socket);
Ok(self)
}
}
}

/// Sets the remote socket of the request.
///
/// # Examples
///
/// ```
/// use lang_handler::RequestBuilder;
///
/// let request = RequestBuilder::new()
/// .remote_socket("127.0.0.1:8080").expect("invalid remote socket")
/// .build();
///
/// assert_eq!(request.remote_socket(), "127.0.0.1:8080");
/// ```
pub fn remote_socket<T>(mut self, remote_socket: T) -> Result<Self, AddrParseError>
where
T: Into<String>,
{
match remote_socket.into().parse() {
Err(e) => Err(e),
Ok(remote_socket) => {
self.remote_socket = Some(remote_socket);
Ok(self)
}
}
}

/// Builds the request.
///
/// # Examples
Expand All @@ -395,6 +521,8 @@ impl RequestBuilder {
.unwrap_or_else(|| Url::parse("http://example.com").unwrap()),
headers: self.headers,
body: self.body.freeze(),
local_socket: self.local_socket,
remote_socket: self.remote_socket,
}
}
}
37 changes: 24 additions & 13 deletions crates/php/src/embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,11 +727,6 @@ pub extern "C" fn sapi_module_register_server_variables(vars: *mut ext_php_rs::t
c"".as_ptr()
};

// php_register_variable(cstr("PATH").unwrap(), cstr("/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin").unwrap(), vars);
// php_register_variable(cstr("SERVER_SIGNATURE").unwrap(), cstr("
// Apache/2.4.62 (Debian) Server at localhost Port 8080

// ").unwrap(), vars);
php_register_variable(
cstr("REQUEST_SCHEME").unwrap(),
cstr(request.url().scheme()).unwrap(),
Expand Down Expand Up @@ -773,15 +768,31 @@ pub extern "C" fn sapi_module_register_server_variables(vars: *mut ext_php_rs::t
vars,
);

// TODO: REMOTE_ADDR, REMOTE_PORT
if let Some(info) = request.local_socket() {
php_register_variable(
cstr("SERVER_ADDR").unwrap(),
cstr(info.ip().to_string()).unwrap(),
vars,
);
php_register_variable(
cstr("SERVER_PORT").unwrap(),
cstr(info.port().to_string()).unwrap(),
vars,
);
}

// TODO: This should pull from the _real_ headers
php_register_variable(cstr("HTTP_HOST").unwrap(), c"localhost:3000".as_ptr(), vars);
php_register_variable(cstr("SERVER_NAME").unwrap(), c"localhost".as_ptr(), vars);
php_register_variable(cstr("SERVER_ADDR").unwrap(), c"172.19.0.2".as_ptr(), vars);
php_register_variable(cstr("SERVER_PORT").unwrap(), c"3000".as_ptr(), vars);
php_register_variable(cstr("REMOTE_ADDR").unwrap(), c"192.168.65.1".as_ptr(), vars);
php_register_variable(cstr("REMOTE_PORT").unwrap(), c"21845".as_ptr(), vars);
if let Some(info) = request.remote_socket() {
php_register_variable(
cstr("REMOTE_ADDR").unwrap(),
cstr(info.ip().to_string()).unwrap(),
vars,
);
php_register_variable(
cstr("REMOTE_PORT").unwrap(),
cstr(info.port().to_string()).unwrap(),
vars,
);
}

if !req_info.request_method.is_null() {
php_register_variable(
Expand Down
Loading
Loading