From 8ba4055e13d7c2b9e410a2fbf837092559efdc2d Mon Sep 17 00:00:00 2001 From: Marin Minnerly Date: Sun, 14 Jan 2024 21:31:23 -0800 Subject: [PATCH] Add net.serve `address` property --- src/lune/builtins/net/config.rs | 6 ++++++ src/lune/builtins/net/mod.rs | 30 +++++++++++++++++++++++++++--- src/lune/builtins/net/server.rs | 16 ++++++++++++---- tests/net/serve/requests.luau | 24 ++++++++++++------------ 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/src/lune/builtins/net/config.rs b/src/lune/builtins/net/config.rs index b754ca8..737fea1 100644 --- a/src/lune/builtins/net/config.rs +++ b/src/lune/builtins/net/config.rs @@ -60,6 +60,7 @@ impl FromLua<'_> for RequestConfig { fn from_lua(value: LuaValue, lua: &Lua) -> LuaResult { // If we just got a string we assume its a GET request to a given url if let LuaValue::String(s) = value { + println!("{:?}", s); return Ok(Self { url: s.to_string_lossy().to_string(), method: Method::GET, @@ -140,9 +141,11 @@ impl FromLua<'_> for RequestConfig { // Net serve config +#[derive(Debug)] pub struct ServeConfig<'a> { pub handle_request: LuaFunction<'a>, pub handle_web_socket: Option>, + pub address: Option>, } impl<'lua> FromLua<'lua> for ServeConfig<'lua> { @@ -152,11 +155,13 @@ impl<'lua> FromLua<'lua> for ServeConfig<'lua> { return Ok(ServeConfig { handle_request: f.clone(), handle_web_socket: None, + address: None, }) } LuaValue::Table(t) => { let handle_request: Option = t.raw_get("handleRequest")?; let handle_web_socket: Option = t.raw_get("handleWebSocket")?; + let address: Option = t.raw_get("address")?; if handle_request.is_some() || handle_web_socket.is_some() { return Ok(ServeConfig { handle_request: handle_request.unwrap_or_else(|| { @@ -174,6 +179,7 @@ impl<'lua> FromLua<'lua> for ServeConfig<'lua> { .expect("Failed to create default http responder function") }), handle_web_socket, + address, }); } else { Some("Missing handleRequest and / or handleWebSocket".to_string()) diff --git a/src/lune/builtins/net/mod.rs b/src/lune/builtins/net/mod.rs index cf9e7ab..9e4680d 100644 --- a/src/lune/builtins/net/mod.rs +++ b/src/lune/builtins/net/mod.rs @@ -1,10 +1,16 @@ +use std::net::Ipv4Addr; + use mlua::prelude::*; use hyper::header::CONTENT_ENCODING; +use regex::Regex; use crate::lune::{scheduler::Scheduler, util::TableBuilder}; -use self::{server::create_server, util::header_map_to_table}; +use self::{ + server::{bind_to_addr, create_server}, + util::header_map_to_table, +}; use super::serde::{ compress_decompress::{decompress, CompressDecompressFormat}, @@ -21,7 +27,6 @@ mod websocket; use client::{NetClient, NetClientBuilder}; use config::{RequestConfig, ServeConfig}; -use server::bind_to_localhost; use websocket::NetWebSocket; pub fn create(lua: &'static Lua) -> LuaResult { @@ -64,6 +69,8 @@ async fn net_request<'lua>(lua: &'lua Lua, config: RequestConfig) -> LuaResult( where 'lua: 'static, // FIXME: Get rid of static lifetime bound here { + println!("port {:?}", port); + let sched = lua .app_data_ref::<&Scheduler>() .expect("Lua struct is missing scheduler"); - let builder = bind_to_localhost(port)?; + println!("config {:?}", config); + + let address_pattern = Regex::new(r"(?:.*:\/\/)?([\d\.]+)(?::\d+)?").unwrap(); + + let address = match &config.address { + Some(addr) => { + let caps = address_pattern.captures(addr.to_str()?).unwrap(); + println!("captures {:?}", &caps); + caps[1].parse::()? + } + None => Ipv4Addr::new(127, 0, 0, 1), + }; + + println!("address {:?}", address); + + let builder = bind_to_addr(address, port)?; create_server(lua, &sched, config, builder) } diff --git a/src/lune/builtins/net/server.rs b/src/lune/builtins/net/server.rs index 97f22c7..6d2fdcb 100644 --- a/src/lune/builtins/net/server.rs +++ b/src/lune/builtins/net/server.rs @@ -1,4 +1,9 @@ -use std::{collections::HashMap, convert::Infallible, net::SocketAddr, sync::Arc}; +use std::{ + collections::HashMap, + convert::Infallible, + net::{Ipv4Addr, SocketAddr}, + sync::Arc, +}; use hyper::{ server::{conn::AddrIncoming, Builder}, @@ -20,12 +25,15 @@ use super::{ websocket::NetWebSocket, }; -pub(super) fn bind_to_localhost(port: u16) -> LuaResult> { - let addr = SocketAddr::from(([127, 0, 0, 1], port)); +pub(super) fn bind_to_addr(address: Ipv4Addr, port: u16) -> LuaResult> { + let addr = SocketAddr::from((address, port)); + + println!("attempting to bind to {:?}", addr); + match Server::try_bind(&addr) { Ok(b) => Ok(b), Err(e) => Err(LuaError::external(format!( - "Failed to bind to localhost on port {port}\n{}", + "Failed to bind to {addr}\n{}", e.to_string() .replace("error creating server listener: ", "> ") ))), diff --git a/tests/net/serve/requests.luau b/tests/net/serve/requests.luau index 88e7e30..02751a1 100644 --- a/tests/net/serve/requests.luau +++ b/tests/net/serve/requests.luau @@ -5,12 +5,12 @@ local task = require("@lune/task") local PORT = 8080 local URL = `http://127.0.0.1:{PORT}` -local URL_EXTERNAL = `http://0.0.0.0:{PORT}` +local URL_EXTERNAL = `http://0.0.0.0` local RESPONSE = "Hello, lune!" -- A server should never be running before testing local isRunning = pcall(net.request, URL) -assert(not isRunning, `A server is already running at {URL}`) +assert(not isRunning, `a server is already running at {URL}`) -- Serve should not block the thread from continuing @@ -21,8 +21,6 @@ local thread = task.delay(1, function() end) local handle = net.serve(PORT, function(request) - -- print("Request:", request) - -- print("Responding with", RESPONSE) assert(request.path == "/some/path") assert(request.query.key == "param2") assert(request.query.key2 == "param3") @@ -84,13 +82,15 @@ assert( ) -- Serve should be able to bind to other IP addresses -handle = net.serve(URL_EXTERNAL, function(request) - assert(request.path == "/some/path") - assert(request.query.key == "param2") - assert(request.query.key2 == "param3") - return RESPONSE -end) +local handle2 = net.serve(PORT, { + address = URL_EXTERNAL, + handleRequest = function(request) + return `Response from {URL_EXTERNAL}:{PORT}` + end, +}) -- And any requests to that IP should succeed -response = net.request(URL_EXTERNAL .. "/some/path?key=param1&key=param2&key2=param3").body -assert(response == RESPONSE, "Invalid response from server") +local response3 = net.request(`{URL_EXTERNAL}:{PORT}`).body +assert(response3 ~= nil, "Invalid response from server") + +handle2.stop()