-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ca98463
commit da26267
Showing
9 changed files
with
296 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
/target | ||
Cargo.lock | ||
credentials.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,15 @@ | ||
#!/bin/bash | ||
# Build the Docker image for the container. | ||
# Build the Docker dependencies image. | ||
# | ||
# NOTE: You have to run this script once first, | ||
# and afterwards you can run the following | ||
# script to start the container: ./start.sh | ||
# and afterwards you have to run the following | ||
# script to build the production Docker | ||
# image: ./prod.sh | ||
|
||
rust_playground_api_deps() { | ||
input_str="$@" | ||
|
||
docker build -t rust_playground_api:latest . | ||
docker build -t rust_playground_api_deps:latest -f deps/Dockerfile . | ||
} | ||
|
||
rust_playground_api_deps "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# --- dependencies image --- | ||
FROM rust:latest | ||
|
||
RUN USER=root cargo new --bin rust-playground-api | ||
|
||
WORKDIR ./rust-playground-api | ||
|
||
COPY ./Cargo.toml ./Cargo.toml | ||
|
||
ADD . ./ | ||
ADD ./src ./src | ||
|
||
RUN cargo build --release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/bin/bash | ||
# Build the Docker image for the container. | ||
# | ||
# NOTE: You have to run this script once first, | ||
# and afterwards you can run the following | ||
# script to start the container: ./start.sh | ||
|
||
rust_playground_api_prod() { | ||
input_str="$@" | ||
|
||
docker build -t gcr.io/rust-playground-api/rust_playground_api:latest . | ||
} | ||
|
||
rust_playground_api_prod "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/bash | ||
|
||
docker push gcr.io/rust-playground-api/rust_playground_api:latest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,240 @@ | ||
/* Borrowed and modified example from: | ||
https://blog.logrocket.com/packaging-a-rust-web-service-using-docker/ | ||
*/ | ||
|
||
use warp::{Filter, Rejection, Reply}; | ||
use serde::Serialize; | ||
use std::env; | ||
use std::error::Error; | ||
use std::net::IpAddr; | ||
use std::process::Command; | ||
use warp::http::header::{HeaderMap, HeaderValue}; | ||
use warp::http::StatusCode; | ||
use warp::reject::Rejection; | ||
use warp::{reject, Filter, Reply}; | ||
use warp_real_ip::real_ip; | ||
|
||
type Result<T> = std::result::Result<T, Rejection>; | ||
|
||
#[derive(Debug, Serialize)] | ||
struct ErrorMessage { | ||
code: u16, | ||
message: String, | ||
} | ||
|
||
impl reject::Reject for ErrorMessage {} | ||
|
||
#[derive(Debug)] | ||
struct DivideByZero; | ||
|
||
impl reject::Reject for DivideByZero {} | ||
|
||
async fn health_handler(addr: String) -> Result<impl Reply> { | ||
println!("|info| GET /health | from: {}", addr); | ||
|
||
Ok("{\"code\": 200, \"message\": \"200 OK\"}") | ||
} | ||
|
||
async fn asm_handler(addr: String) -> Result<impl Reply> { | ||
println!("|info| GET /asm | from: {}", addr); | ||
|
||
let output = Command::new("/bin/bash") | ||
.arg("-c") | ||
.arg("./asm.sh") | ||
.output() | ||
.expect("failed to execute process"); | ||
|
||
let stdout = String::from_utf8_lossy(&output.stdout).to_string(); | ||
|
||
println!("status: {}", output.status); | ||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); | ||
|
||
Ok(stdout) | ||
} | ||
|
||
async fn build_handler(addr: String) -> Result<impl Reply> { | ||
println!("|info| GET /build | from: {}", addr); | ||
|
||
let output = Command::new("/bin/bash") | ||
.arg("-c") | ||
.arg("./build.sh") | ||
.output() | ||
.expect("failed to execute process"); | ||
|
||
let stdout = String::from_utf8_lossy(&output.stdout).to_string(); | ||
|
||
println!("status: {}", output.status); | ||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); | ||
|
||
Ok(stdout) | ||
} | ||
|
||
async fn run_handler(addr: String) -> Result<impl Reply> { | ||
println!("|info| GET / (or GET /run) | from: {}", addr); | ||
|
||
let output = Command::new("/bin/bash") | ||
.arg("-c") | ||
.arg("./run.sh") | ||
.output() | ||
.expect("failed to execute process"); | ||
|
||
let stdout = String::from_utf8_lossy(&output.stdout).to_string(); | ||
|
||
println!("status: {}", output.status); | ||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); | ||
|
||
Ok(stdout) | ||
} | ||
|
||
async fn test_handler(addr: String) -> Result<impl Reply> { | ||
println!("|info| GET /test | from: {}", addr); | ||
|
||
let output = Command::new("/bin/bash") | ||
.arg("-c") | ||
.arg("./test.sh") | ||
.output() | ||
.expect("failed to execute process"); | ||
|
||
let stdout = String::from_utf8_lossy(&output.stdout).to_string(); | ||
|
||
println!("status: {}", output.status); | ||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); | ||
|
||
Ok(stdout) | ||
} | ||
|
||
async fn wasm_handler(addr: String) -> Result<impl Reply> { | ||
println!("|info| GET /wasm | from: {}", addr); | ||
|
||
let output = Command::new("/bin/bash") | ||
.arg("-c") | ||
.arg("./wasm.sh") | ||
.output() | ||
.expect("failed to execute process"); | ||
|
||
let stdout = String::from_utf8_lossy(&output.stdout).to_string(); | ||
|
||
println!("status: {}", output.status); | ||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); | ||
|
||
Ok(stdout) | ||
} | ||
|
||
async fn rejection_handler(err: Rejection) -> Result<impl Reply> { | ||
let code; | ||
let message; | ||
|
||
if err.is_not_found() { | ||
code = StatusCode::NOT_FOUND; | ||
message = "404 Not Found"; | ||
} else if let Some(DivideByZero) = err.find() { | ||
code = StatusCode::BAD_REQUEST; | ||
message = "400 Bad Request"; | ||
} else if let Some(e) = err.find::<warp::filters::body::BodyDeserializeError>() { | ||
message = match e.source() { | ||
Some(cause) => { | ||
if cause.to_string().contains("denom") { | ||
"400 Bad Request" | ||
} else { | ||
"400 Bad Request" | ||
} | ||
} | ||
None => "400 Bad Request", | ||
}; | ||
code = StatusCode::BAD_REQUEST; | ||
} else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() { | ||
code = StatusCode::METHOD_NOT_ALLOWED; | ||
message = "405 Method Not Allowed"; | ||
} else { | ||
eprintln!("unhandled rejection: {:?}", err); | ||
code = StatusCode::INTERNAL_SERVER_ERROR; | ||
message = "500 Internal Server Error"; | ||
} | ||
|
||
let json = warp::reply::json(&ErrorMessage { | ||
code: code.as_u16(), | ||
message: message.into(), | ||
}); | ||
|
||
Ok(warp::reply::with_status(json, code)) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
let health_route = warp::path!("health").and_then(health_handler); | ||
let port_default: u16 = 8080; | ||
|
||
let routes = health_route.with(warp::cors().allow_any_origin()); | ||
let port: u16 = { | ||
env::var("PORT") | ||
.unwrap_or(format!("{}", port_default)) | ||
.parse() | ||
.unwrap_or(port_default) | ||
}; | ||
|
||
println!("Started server at: http://localhost:8080"); | ||
warp::serve(routes).run(([0, 0, 0, 0], 8080)).await; | ||
} | ||
let proxy_addr = [127, 0, 0, 1].into(); | ||
|
||
let mut res_headers = HeaderMap::new(); | ||
res_headers.insert( | ||
"Content-Type", | ||
HeaderValue::from_static("application/json; charset=utf-8"), | ||
); | ||
|
||
let health_route = warp::path!("health").and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(health_handler), | ||
); | ||
|
||
let asm_route = warp::path!("asm").and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(asm_handler), | ||
); | ||
|
||
let build_route = warp::path!("build").and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(build_handler), | ||
); | ||
|
||
let run_route = warp::path!("run").and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(run_handler), | ||
); | ||
|
||
let test_route = warp::path!("test").and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(test_handler), | ||
); | ||
|
||
let wasm_route = warp::path!("wasm").and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(wasm_handler), | ||
); | ||
|
||
let index_route = warp::path::end().and( | ||
real_ip(vec![proxy_addr]) | ||
.map(|addr: Option<IpAddr>| format!("{:?}", addr.unwrap())) | ||
.and_then(run_handler), | ||
); | ||
|
||
let routes = warp::any().and( | ||
warp::get() | ||
.and( | ||
health_route | ||
.or(asm_route) | ||
.or(build_route) | ||
.or(run_route) | ||
.or(test_route) | ||
.or(wasm_route) | ||
.or(index_route) | ||
.recover(rejection_handler) | ||
.with(warp::reply::with::headers(res_headers.clone())) | ||
.with(warp::cors().allow_any_origin()), | ||
) | ||
.recover(rejection_handler) | ||
.with(warp::reply::with::headers(res_headers.clone())) | ||
.with(warp::cors().allow_any_origin()), | ||
); | ||
|
||
println!("Started server at: http://localhost:{}", port); | ||
|
||
async fn health_handler() -> Result<impl Reply> { | ||
Ok("OK") | ||
warp::serve(routes).run(([0, 0, 0, 0], port)).await; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters