Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add flag for router IP local run #565

Merged
merged 13 commits into from
Jan 10, 2023
Merged
3 changes: 3 additions & 0 deletions cargo-shuttle/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ pub struct RunArgs {
/// port to start service on
#[clap(long, default_value = "8000")]
pub port: u16,
/// use 0.0.0.0 instead of localhost (for usage with local external devices)
#[clap(long)]
pub external: bool,
}

#[derive(Parser, Debug)]
Expand Down
8 changes: 7 additions & 1 deletion cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,13 @@ impl Shuttle {
secrets,
working_directory.to_path_buf(),
)?;
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), run_args.port);
let addr = if run_args.external {
std::net::IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
} else {
Ipv4Addr::LOCALHOST.into()
};

let addr = SocketAddr::new(addr, run_args.port);

trace!("loading project");
println!(
Expand Down
105 changes: 62 additions & 43 deletions cargo-shuttle/tests/integration/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ use std::{fs::canonicalize, process::exit, time::Duration};
use tokio::time::sleep;

/// creates a `cargo-shuttle` run instance with some reasonable defaults set.
async fn cargo_shuttle_run(working_directory: &str) -> u16 {
async fn cargo_shuttle_run(working_directory: &str, external: bool) -> String {
let working_directory = canonicalize(working_directory).unwrap();

let port = pick_unused_port().unwrap();
let run_args = RunArgs { port };

let url = if !external {
format!("http://localhost:{port}")
} else {
format!("http://0.0.0.0:{port}")
};

let run_args = RunArgs { port, external };

let runner = Shuttle::new().unwrap().run(Args {
api_url: Some("http://shuttle.invalid:80".to_string()),
Expand All @@ -34,28 +42,23 @@ async fn cargo_shuttle_run(working_directory: &str) -> u16 {
tokio::spawn(runner);

// Wait for service to be responsive
while (reqwest::Client::new()
.get(format!("http://localhost:{port}"))
.send()
.await)
.is_err()
{
while (reqwest::Client::new().get(url.clone()).send().await).is_err() {
println!(
"waiting for '{}' to start up...",
working_directory.display()
);
sleep(Duration::from_millis(350)).await;
}

port
url
}

#[tokio::test(flavor = "multi_thread")]
async fn rocket_hello_world() {
let port = cargo_shuttle_run("../examples/rocket/hello-world").await;
let url = cargo_shuttle_run("../examples/rocket/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -68,10 +71,10 @@ async fn rocket_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn rocket_secrets() {
let port = cargo_shuttle_run("../examples/rocket/secrets").await;
let url = cargo_shuttle_run("../examples/rocket/secrets", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/secret"))
.get(format!("{url}/secret"))
.send()
.await
.unwrap()
Expand All @@ -85,11 +88,11 @@ async fn rocket_secrets() {
// This example uses a shared Postgres. Thus local runs should create a docker container for it.
#[tokio::test(flavor = "multi_thread")]
async fn rocket_postgres() {
let port = cargo_shuttle_run("../examples/rocket/postgres").await;
let url = cargo_shuttle_run("../examples/rocket/postgres", false).await;
let client = reqwest::Client::new();

let post_text = client
.post(format!("http://localhost:{port}/todo"))
.post(format!("{url}/todo"))
.body("{\"note\": \"Deploy to shuttle\"}")
.send()
.await
Expand All @@ -101,7 +104,7 @@ async fn rocket_postgres() {
assert_eq!(post_text, "{\"id\":1,\"note\":\"Deploy to shuttle\"}");

let request_text = client
.get(format!("http://localhost:{port}/todo/1"))
.get(format!("{url}/todo/1"))
.send()
.await
.unwrap()
Expand All @@ -114,11 +117,11 @@ async fn rocket_postgres() {

#[tokio::test(flavor = "multi_thread")]
async fn rocket_authentication() {
let port = cargo_shuttle_run("../examples/rocket/authentication").await;
let url = cargo_shuttle_run("../examples/rocket/authentication", false).await;
let client = reqwest::Client::new();

let public_text = client
.get(format!("http://localhost:{port}/public"))
.get(format!("{url}/public"))
.send()
.await
.unwrap()
Expand All @@ -132,7 +135,7 @@ async fn rocket_authentication() {
);

let private_status = client
.get(format!("http://localhost:{port}/private"))
.get(format!("{url}/private"))
.send()
.await
.unwrap()
Expand All @@ -141,7 +144,7 @@ async fn rocket_authentication() {
assert_eq!(private_status, StatusCode::FORBIDDEN);

let body = client
.post(format!("http://localhost:{port}/login"))
.post(format!("{url}/login"))
.body("{\"username\": \"username\", \"password\": \"password\"}")
.send()
.await
Expand All @@ -153,7 +156,7 @@ async fn rocket_authentication() {
let token = format!("Bearer {}", json["token"].as_str().unwrap());

let private_text = client
.get(format!("http://localhost:{port}/private"))
.get(format!("{url}/private"))
.header("Authorization", token)
.send()
.await
Expand All @@ -170,10 +173,10 @@ async fn rocket_authentication() {

#[tokio::test(flavor = "multi_thread")]
async fn actix_web_hello_world() {
let port = cargo_shuttle_run("../examples/actix-web/hello-world").await;
let url = cargo_shuttle_run("../examples/actix-web/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -186,10 +189,10 @@ async fn actix_web_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn axum_hello_world() {
let port = cargo_shuttle_run("../examples/axum/hello-world").await;
let url = cargo_shuttle_run("../examples/axum/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -202,10 +205,10 @@ async fn axum_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn tide_hello_world() {
let port = cargo_shuttle_run("../examples/tide/hello-world").await;
let url = cargo_shuttle_run("../examples/tide/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -218,10 +221,10 @@ async fn tide_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn tower_hello_world() {
let port = cargo_shuttle_run("../examples/tower/hello-world").await;
let url = cargo_shuttle_run("../examples/tower/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -234,10 +237,10 @@ async fn tower_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn warp_hello_world() {
let port = cargo_shuttle_run("../examples/warp/hello-world").await;
let url = cargo_shuttle_run("../examples/warp/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -250,10 +253,10 @@ async fn warp_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn poem_hello_world() {
let port = cargo_shuttle_run("../examples/poem/hello-world").await;
let url = cargo_shuttle_run("../examples/poem/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -267,11 +270,11 @@ async fn poem_hello_world() {
// This example uses a shared Postgres. Thus local runs should create a docker container for it.
#[tokio::test(flavor = "multi_thread")]
async fn poem_postgres() {
let port = cargo_shuttle_run("../examples/poem/postgres").await;
let url = cargo_shuttle_run("../examples/poem/postgres", false).await;
let client = reqwest::Client::new();

let post_text = client
.post(format!("http://localhost:{port}/todo"))
.post(format!("{url}/todo"))
.body("{\"note\": \"Deploy to shuttle\"}")
.header("content-type", "application/json")
.send()
Expand All @@ -284,7 +287,7 @@ async fn poem_postgres() {
assert_eq!(post_text, "{\"id\":1,\"note\":\"Deploy to shuttle\"}");

let request_text = client
.get(format!("http://localhost:{port}/todo/1"))
.get(format!("{url}/todo/1"))
.send()
.await
.unwrap()
Expand All @@ -298,12 +301,12 @@ async fn poem_postgres() {
// This example uses a shared MongoDb. Thus local runs should create a docker container for it.
#[tokio::test(flavor = "multi_thread")]
async fn poem_mongodb() {
let port = cargo_shuttle_run("../examples/poem/mongodb").await;
let url = cargo_shuttle_run("../examples/poem/mongodb", false).await;
let client = reqwest::Client::new();

// Post a todo note and get the persisted todo objectId
let post_text = client
.post(format!("http://localhost:{port}/todo"))
.post(format!("{url}/todo"))
.body("{\"note\": \"Deploy to shuttle\"}")
.header("content-type", "application/json")
.send()
Expand All @@ -317,7 +320,7 @@ async fn poem_mongodb() {
assert_eq!(post_text.len(), 24);

let request_text = client
.get(format!("http://localhost:{port}/todo/{post_text}"))
.get(format!("{url}/todo/{post_text}"))
.send()
.await
.unwrap()
Expand All @@ -330,10 +333,10 @@ async fn poem_mongodb() {

#[tokio::test(flavor = "multi_thread")]
async fn salvo_hello_world() {
let port = cargo_shuttle_run("../examples/salvo/hello-world").await;
let url = cargo_shuttle_run("../examples/salvo/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -346,10 +349,10 @@ async fn salvo_hello_world() {

#[tokio::test(flavor = "multi_thread")]
async fn thruster_hello_world() {
let port = cargo_shuttle_run("../examples/thruster/hello-world").await;
let url = cargo_shuttle_run("../examples/thruster/hello-world", false).await;

let request_text = reqwest::Client::new()
.get(format!("http://localhost:{port}/hello"))
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
Expand All @@ -359,3 +362,19 @@ async fn thruster_hello_world() {

assert_eq!(request_text, "Hello, World!");
}

#[tokio::test(flavor = "multi_thread")]
async fn rocket_hello_world_with_router_ip() {
let url = cargo_shuttle_run("../examples/rocket/hello-world", true).await;

let request_text = reqwest::Client::new()
.get(format!("{url}/hello"))
.send()
.await
.unwrap()
.text()
.await
.unwrap();

assert_eq!(request_text, "Hello, world!");
}
2 changes: 1 addition & 1 deletion service/tests/integration/helpers/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ pub fn build_so_create_loader(resources: &str, crate_name: &str) -> Result<Loade

let so_path = crate_dir.join("target/release").join(lib_name);

Loader::from_so_file(&so_path)
Loader::from_so_file(so_path)
}