Skip to content

Commit

Permalink
Serve from other IPs (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
vocksel authored Jan 19, 2024
1 parent 1b25ed2 commit 3c68d8e
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
5 changes: 5 additions & 0 deletions src/lune/builtins/net/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,11 @@ impl FromLua<'_> for RequestConfig {

// Net serve config

#[derive(Debug)]
pub struct ServeConfig<'a> {
pub handle_request: LuaFunction<'a>,
pub handle_web_socket: Option<LuaFunction<'a>>,
pub address: Option<LuaString<'a>>,
}

impl<'lua> FromLua<'lua> for ServeConfig<'lua> {
Expand All @@ -152,11 +154,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<LuaFunction> = t.raw_get("handleRequest")?;
let handle_web_socket: Option<LuaFunction> = t.raw_get("handleWebSocket")?;
let address: Option<LuaString> = t.raw_get("address")?;
if handle_request.is_some() || handle_web_socket.is_some() {
return Ok(ServeConfig {
handle_request: handle_request.unwrap_or_else(|| {
Expand All @@ -174,6 +178,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())
Expand Down
27 changes: 24 additions & 3 deletions src/lune/builtins/net/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use std::net::Ipv4Addr;

use mlua::prelude::*;

use hyper::header::CONTENT_ENCODING;

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},
Expand All @@ -21,9 +26,10 @@ mod websocket;

use client::{NetClient, NetClientBuilder};
use config::{RequestConfig, ServeConfig};
use server::bind_to_localhost;
use websocket::NetWebSocket;

const DEFAULT_IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);

pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
NetClientBuilder::new()
.headers(&[("User-Agent", create_user_agent_header())])?
Expand Down Expand Up @@ -137,7 +143,22 @@ where
.app_data_ref::<&Scheduler>()
.expect("Lua struct is missing scheduler");

let builder = bind_to_localhost(port)?;
let address: Ipv4Addr = match &config.address {
Some(addr) => {
let addr_str = addr.to_str()?;

addr_str
.trim_start_matches("http://")
.trim_start_matches("https://")
.parse()
.map_err(|_e| LuaError::RuntimeError(format!(
"IP address format is incorrect (expected an IP in the form 'http://0.0.0.0' or '0.0.0.0', got '{addr_str}')"
)))?
}
None => DEFAULT_IP_ADDRESS,
};

let builder = bind_to_addr(address, port)?;

create_server(lua, &sched, config, builder)
}
Expand Down
14 changes: 10 additions & 4 deletions src/lune/builtins/net/server.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -20,12 +25,13 @@ use super::{
websocket::NetWebSocket,
};

pub(super) fn bind_to_localhost(port: u16) -> LuaResult<Builder<AddrIncoming>> {
let addr = SocketAddr::from(([127, 0, 0, 1], port));
pub(super) fn bind_to_addr(address: Ipv4Addr, port: u16) -> LuaResult<Builder<AddrIncoming>> {
let addr = SocketAddr::from((address, port));

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: ", "> ")
))),
Expand Down
34 changes: 34 additions & 0 deletions tests/net/serve/requests.luau
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ local task = require("@lune/task")

local PORT = 8080
local URL = `http://127.0.0.1:{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}`)

-- Serve should not block the thread from continuing

local thread = task.delay(1, function()
Expand Down Expand Up @@ -77,3 +82,32 @@ assert(
or string.find(message, "shut down"),
"The error message for calling stop twice on the net serve handle should be descriptive"
)

-- Serve should be able to bind to other IP addresses
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
local response3 = net.request(`{URL_EXTERNAL}:{PORT}`).body
assert(response3 ~= nil, "Invalid response from server")

handle2.stop()

-- Attempting to serve with a malformed IP address should throw an error
local success3 = pcall(function()
net.serve(8080, {
address = "a.b.c.d",
handleRequest = function()
return RESPONSE
end,
})
end)

assert(not success3, "Server was created with malformed address")

-- We have to manually exit so Windows CI doesn't get stuck forever
process.exit(0)

0 comments on commit 3c68d8e

Please sign in to comment.