diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7137ca2..54be8f3 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -25,7 +25,7 @@ jobs: RUST_BACKTRACE=full cargo build --verbose mkdir -p rust-playground-api/rust-playground-api cp target/debug/main rust-playground-api/rust-playground-api/rust-playground-api - cp asm.sh build.sh run.sh test.sh wasm.sh rust-playground-api/rust-playground-api/ + cp gist.sh asm-gist.sh build-gist.sh run-gist.sh test-gist.sh wasm-gist.sh rust-playground-api/rust-playground-api/ chmod 755 rust-playground-api/rust-playground-api/rust-playground-api - name: rust-playground-api-debug-linux-x86_64 @@ -48,7 +48,7 @@ jobs: RUST_BACKTRACE=full cargo build --release --verbose mkdir -p rust-playground-api/rust-playground-api cp target/release/main rust-playground-api/rust-playground-api/rust-playground-api - cp asm.sh build.sh run.sh test.sh wasm.sh rust-playground-api/rust-playground-api/ + cp gist.sh asm-gist.sh build-gist.sh run-gist.sh test-gist.sh wasm-gist.sh rust-playground-api/rust-playground-api/ strip -s rust-playground-api/rust-playground-api/rust-playground-api chmod 755 rust-playground-api/rust-playground-api/rust-playground-api diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0f8368c..398d661 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,7 +39,7 @@ debug-linux-x86_64: - RUST_BACKTRACE=full cargo build --verbose - mkdir -p rust-playground-api - cp target/debug/main rust-playground-api/rust-playground-api - - cp asm.sh build.sh run.sh test.sh wasm.sh rust-playground-api/ + - cp gist.sh asm-gist.sh build-gist.sh run-gist.sh test-gist.sh wasm-gist.sh rust-playground-api/ - chmod 755 rust-playground-api/rust-playground-api artifacts: name: rust-playground-api-debug-linux-x86_64 @@ -60,7 +60,7 @@ release-linux-x86_64: - RUST_BACKTRACE=full cargo build --release --verbose - mkdir -p rust-playground-api - cp target/release/main rust-playground-api/rust-playground-api - - cp asm.sh build.sh run.sh test.sh wasm.sh rust-playground-api/ + - cp gist.sh asm-gist.sh build-gist.sh run-gist.sh test-gist.sh wasm-gist.sh rust-playground-api/ - strip -s rust-playground-api/rust-playground-api - chmod 755 rust-playground-api/rust-playground-api artifacts: diff --git a/Dockerfile b/Dockerfile index 3c71ba2..c44fd3e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,11 @@ ENV TZ=Etc/UTC \ WORKDIR ./rust-playground-api +COPY ./Cargo.toml ./Cargo.toml + +ADD . ./ +ADD ./src ./src + RUN cargo build --release RUN rm src/*.rs || true; \ @@ -42,11 +47,12 @@ RUN groupadd $APP_USER && \ mkdir -p ${APP} COPY --from=build /rust-playground-api/target/release/main ${APP}/main -COPY --from=build /rust-playground-api/asm.sh ${APP}/ -COPY --from=build /rust-playground-api/build.sh ${APP}/ -COPY --from=build /rust-playground-api/run.sh ${APP}/ -COPY --from=build /rust-playground-api/test.sh ${APP}/ -COPY --from=build /rust-playground-api/wasm.sh ${APP}/ +COPY --from=build /rust-playground-api/gist.sh ${APP}/ +COPY --from=build /rust-playground-api/asm-gist.sh ${APP}/ +COPY --from=build /rust-playground-api/build-gist.sh ${APP}/ +COPY --from=build /rust-playground-api/run-gist.sh ${APP}/ +COPY --from=build /rust-playground-api/test-gist.sh ${APP}/ +COPY --from=build /rust-playground-api/wasm-gist.sh ${APP}/ COPY --from=build /rust-playground-api/src/example1/main.rs ${APP}/src/example1/main.rs RUN chown -R $APP_USER:$APP_USER ${APP} diff --git a/README.md b/README.md index caf2fff..073ba4b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ --- -v0.0.1 - "Hello, world! version" - 2021 by `Jeremy Carter ` +v0.1.0 - 2021 by `Jeremy Carter ` GitLab: [https://gitlab.com/defcronyke/rust-playground-api](https://gitlab.com/defcronyke/rust-playground-api) GitHub: [https://github.com/defcronyke/rust-playground-api](https://github.com/defcronyke/rust-playground-api) @@ -60,17 +60,38 @@ cd rust-playground-api --- +## Usage + +1. Make a GitHub `secret` or `public` Gist, with your desired `Rust` program code in it: + [https://gist.github.com](https://gist.github.com) + +2. Get the Gist's ID from its URL, for example the `id` value as below: + https://gist.github.com/{username}/{id} + +3. Run the `Rust` code by using the `id` in your GET request, for example: + [http://localhost:8080/?id=1ea016619193533f9ac6cd1d8ae22d58](http://localhost:8080/?id=1ea016619193533f9ac6cd1d8ae22d58) + +--- + ## API routes available -- Run the code: GET / [http://localhost:8080](http://localhost:8080) +_Use your desired "GitHub Gist ID" for the `id` GET query parameter in the example requests below. The `Rust` code in that Gist will be used for +the query._ + +- Run the code: + GET /?id=1ea016619193533f9ac6cd1d8ae22d58 [http://localhost:8080/?id=1ea016619193533f9ac6cd1d8ae22d58](http://localhost:8080/?id=1ea016619193533f9ac6cd1d8ae22d58) -- Run the test suite: GET /test [http://localhost:8080/test](http://localhost:8080/test) +- Run the test suite: + GET /test?id=1ea016619193533f9ac6cd1d8ae22d58 [http://localhost:8080/test?id=1ea016619193533f9ac6cd1d8ae22d58](http://localhost:8080/test?id=1ea016619193533f9ac6cd1d8ae22d58) -- Build the code: GET /build [http://localhost:8080/build](http://localhost:8080/build) +- Build the code: + GET /build?id=1ea016619193533f9ac6cd1d8ae22d58 [http://localhost:8080/build?id=1ea016619193533f9ac6cd1d8ae22d58](http://localhost:8080/build?id=1ea016619193533f9ac6cd1d8ae22d58) -- Build and output WebAssembly of the code: GET /wasm [http://localhost:8080/wasm](http://localhost:8080/wasm) +- Build and output WebAssembly of the code: + GET /wasm?id=1ea016619193533f9ac6cd1d8ae22d58 [http://localhost:8080/wasm?id=1ea016619193533f9ac6cd1d8ae22d58](http://localhost:8080/wasm?id=1ea016619193533f9ac6cd1d8ae22d58) -- Build and output Assembly of the code: GET /asm [http://localhost:8080/asm](http://localhost:8080/asm) +- Build and output Assembly of the code: + GET /asm?id=1ea016619193533f9ac6cd1d8ae22d58 [http://localhost:8080/asm?id=1ea016619193533f9ac6cd1d8ae22d58](http://localhost:8080/asm?id=1ea016619193533f9ac6cd1d8ae22d58) --- diff --git a/asm-gist.sh b/asm-gist.sh new file mode 100755 index 0000000..b6ee194 --- /dev/null +++ b/asm-gist.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Depends on the 'jq' tool. + +rust_playground_api_asm_gist() { + input_str="$@" + + if [ $# -eq 0 ]; then + input_str="1ea016619193533f9ac6cd1d8ae22d58" + fi + + input_str2="$(printf '%s' "$(./gist.sh "$input_str")")" + input_str2="${input_str2%\"}" + input_str2="${input_str2#\"}" + + input_param="$(printf '%b' "$input_str2"|jq -sRr @uri)" + + curl -sL -H 'Content-Type: application/json' -X POST -d '{"channel":"nightly","mode":"debug","edition":"2018","crateType":"bin","tests":false,"code":"'"$input_str2"'","target":"asm","assemblyFlavor":"att","demangleAssembly":"demangle","processAssembly":"filter","backtrace":false}' -H "Referrer: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&code=$input_param" https://play.rust-lang.org/compile +} + +rust_playground_api_asm_gist "$@" diff --git a/build-gist.sh b/build-gist.sh new file mode 100755 index 0000000..a914bfd --- /dev/null +++ b/build-gist.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Depends on the 'jq' tool. + +rust_playground_api_build_gist() { + input_str="$@" + + if [ $# -eq 0 ]; then + input_str="1ea016619193533f9ac6cd1d8ae22d58" + fi + + input_str2="$(printf '%s' "$(./gist.sh "$input_str")")" + input_str2="${input_str2%\"}" + input_str2="${input_str2#\"}" + + input_param="$(printf '%b' "$input_str2"|jq -sRr @uri)" + + curl -sL -H 'Content-Type: application/json' -X POST -d '{"channel":"nightly","mode":"debug","edition":"2018","crateType":"lib","tests":false,"code":"'"$input_str2"'","backtrace":false}' -H "Referrer: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&code=$input_param" https://play.rust-lang.org/execute +} + +rust_playground_api_build_gist "$@" diff --git a/gist.sh b/gist.sh new file mode 100755 index 0000000..8e8b8d1 --- /dev/null +++ b/gist.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Depends on the 'jq' tool. +# +# Example: ./gist.sh 1ea016619193533f9ac6cd1d8ae22d58 + +rust_playground_api_gist() { + input_str="$@" + + curl -sL -H 'Accept: application/vnd.github.v3+json.raw' "https://api.github.com/gists/$input_str" | \ + jq '.files | to_entries | .[0].value.content' +} + +rust_playground_api_gist "$@" diff --git a/run-gist.sh b/run-gist.sh new file mode 100755 index 0000000..1be7d0f --- /dev/null +++ b/run-gist.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Depends on the 'jq' tool. + +rust_playground_api_run_gist() { + input_str="$@" + + if [ $# -eq 0 ]; then + input_str="1ea016619193533f9ac6cd1d8ae22d58" + fi + + input_str2="$(printf '%s' "$(./gist.sh "$input_str")")" + input_str2="${input_str2%\"}" + input_str2="${input_str2#\"}" + + input_param="$(printf '%b' "$input_str2"|jq -sRr @uri)" + + curl -sL -H 'Content-Type: application/json' -X POST -d '{"channel":"nightly","mode":"debug","edition":"2018","crateType":"bin","tests":false,"code":"'"$input_str2"'","backtrace":false}' -H "Referrer: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&code=$input_param" https://play.rust-lang.org/execute +} + +rust_playground_api_run_gist "$@" diff --git a/src/main.rs b/src/main.rs index 8248b68..3aa828b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::env; use std::error::Error; use std::net::IpAddr; @@ -11,6 +11,12 @@ use warp_real_ip::real_ip; type Result = std::result::Result; +/** Gist `id` GET query param. */ +#[derive(Deserialize)] +struct Gist { + id: String, +} + #[derive(Debug, Serialize)] struct ErrorMessage { code: u16, @@ -30,12 +36,20 @@ async fn health_handler(addr: String) -> Result { Ok("{\"code\": 200, \"message\": \"200 OK\"}") } -async fn asm_handler(addr: String) -> Result { - println!("|info| GET /asm | from: {}", addr); +async fn asm_handler(addr: String, id: String) -> Result { + let id_param = { + if id == "" { + "1ea016619193533f9ac6cd1d8ae22d58".to_string() + } else { + id + } + }; + + println!("|info| GET /asm?id={} | from: {}", id_param, addr); let output = Command::new("/bin/bash") .arg("-c") - .arg("./asm.sh") + .arg(format!("./asm-gist.sh {}", id_param)) .output() .expect("failed to execute process"); @@ -47,12 +61,20 @@ async fn asm_handler(addr: String) -> Result { Ok(stdout) } -async fn build_handler(addr: String) -> Result { - println!("|info| GET /build | from: {}", addr); +async fn build_handler(addr: String, id: String) -> Result { + let id_param = { + if id == "" { + "1ea016619193533f9ac6cd1d8ae22d58".to_string() + } else { + id + } + }; + + println!("|info| GET /build?id={} | from: {}", id_param, addr); let output = Command::new("/bin/bash") .arg("-c") - .arg("./build.sh") + .arg(format!("./build-gist.sh {}", id_param)) .output() .expect("failed to execute process"); @@ -64,12 +86,23 @@ async fn build_handler(addr: String) -> Result { Ok(stdout) } -async fn run_handler(addr: String) -> Result { - println!("|info| GET / (or GET /run) | from: {}", addr); +async fn run_handler(addr: String, id: String) -> Result { + let id_param = { + if id == "" { + "1ea016619193533f9ac6cd1d8ae22d58".to_string() + } else { + id + } + }; + + println!( + "|info| GET /?id={} (or GET /run?id={}) | from: {}", + id_param, id_param, addr + ); let output = Command::new("/bin/bash") .arg("-c") - .arg("./run.sh") + .arg(format!("./run-gist.sh {}", id_param)) .output() .expect("failed to execute process"); @@ -81,12 +114,20 @@ async fn run_handler(addr: String) -> Result { Ok(stdout) } -async fn test_handler(addr: String) -> Result { - println!("|info| GET /test | from: {}", addr); +async fn test_handler(addr: String, id: String) -> Result { + let id_param = { + if id == "" { + "1ea016619193533f9ac6cd1d8ae22d58".to_string() + } else { + id + } + }; + + println!("|info| GET /test?id={} | from: {}", id_param, addr); let output = Command::new("/bin/bash") .arg("-c") - .arg("./test.sh") + .arg(format!("./test-gist.sh {}", id_param)) .output() .expect("failed to execute process"); @@ -98,12 +139,20 @@ async fn test_handler(addr: String) -> Result { Ok(stdout) } -async fn wasm_handler(addr: String) -> Result { - println!("|info| GET /wasm | from: {}", addr); +async fn wasm_handler(addr: String, id: String) -> Result { + let id_param = { + if id == "" { + "1ea016619193533f9ac6cd1d8ae22d58".to_string() + } else { + id + } + }; + + println!("|info| GET /wasm?id={} | from: {}", id_param, addr); let output = Command::new("/bin/bash") .arg("-c") - .arg("./wasm.sh") + .arg(format!("./wasm-gist.sh {}", id_param)) .output() .expect("failed to execute process"); @@ -182,36 +231,72 @@ async fn main() { let asm_route = warp::path!("asm").and( real_ip(vec![proxy_addr]) .map(|addr: Option| format!("{:?}", addr.unwrap())) + .and( + warp::query() + .map(|g: Gist| format!("{}", g.id)) + .or(warp::get().map(|| String::default())) + .unify(), + ) .and_then(asm_handler), ); let build_route = warp::path!("build").and( real_ip(vec![proxy_addr]) .map(|addr: Option| format!("{:?}", addr.unwrap())) + .and( + warp::query() + .map(|g: Gist| format!("{}", g.id)) + .or(warp::get().map(|| String::default())) + .unify(), + ) .and_then(build_handler), ); let run_route = warp::path!("run").and( real_ip(vec![proxy_addr]) .map(|addr: Option| format!("{:?}", addr.unwrap())) + .and( + warp::query() + .map(|g: Gist| format!("{}", g.id)) + .or(warp::get().map(|| String::default())) + .unify(), + ) .and_then(run_handler), ); let test_route = warp::path!("test").and( real_ip(vec![proxy_addr]) .map(|addr: Option| format!("{:?}", addr.unwrap())) + .and( + warp::query() + .map(|g: Gist| format!("{}", g.id)) + .or(warp::get().map(|| String::default())) + .unify(), + ) .and_then(test_handler), ); let wasm_route = warp::path!("wasm").and( real_ip(vec![proxy_addr]) .map(|addr: Option| format!("{:?}", addr.unwrap())) + .and( + warp::query() + .map(|g: Gist| format!("{}", g.id)) + .or(warp::get().map(|| String::default())) + .unify(), + ) .and_then(wasm_handler), ); let index_route = warp::path::end().and( real_ip(vec![proxy_addr]) .map(|addr: Option| format!("{:?}", addr.unwrap())) + .and( + warp::query() + .map(|g: Gist| format!("{}", g.id)) + .or(warp::get().map(|| String::default())) + .unify(), + ) .and_then(run_handler), ); diff --git a/test-gist.sh b/test-gist.sh new file mode 100755 index 0000000..2a83a4b --- /dev/null +++ b/test-gist.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Depends on the 'jq' tool. + +rust_playground_api_test_gist() { + input_str="$@" + + if [ $# -eq 0 ]; then + input_str="1ea016619193533f9ac6cd1d8ae22d58" + fi + + input_str2="$(printf '%s' "$(./gist.sh "$input_str")")" + input_str2="${input_str2%\"}" + input_str2="${input_str2#\"}" + + input_param="$(printf '%b' "$input_str2"|jq -sRr @uri)" + + curl -sL -H 'Content-Type: application/json' -X POST -d '{"channel":"nightly","mode":"debug","edition":"2018","crateType":"lib","tests":true,"code":"'"$input_str2"'","backtrace":false}' -H "Referrer: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&code=$input_param" https://play.rust-lang.org/execute +} + +rust_playground_api_test_gist "$@" diff --git a/wasm-gist.sh b/wasm-gist.sh new file mode 100755 index 0000000..dd74855 --- /dev/null +++ b/wasm-gist.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Depends on the 'jq' tool. + +rust_playground_api_wasm_gist() { + input_str="$@" + + if [ $# -eq 0 ]; then + input_str="1ea016619193533f9ac6cd1d8ae22d58" + fi + + input_str2="$(printf '%s' "$(./gist.sh "$input_str")")" + input_str2="${input_str2%\"}" + input_str2="${input_str2#\"}" + + input_param="$(printf '%b' "$input_str2"|jq -sRr @uri)" + + curl -sL -H 'Content-Type: application/json' -X POST -d '{"channel":"nightly","mode":"debug","edition":"2018","crateType":"bin","tests":false,"code":"'"$input_str2"'","target":"wasm","assemblyFlavor":"att","demangleAssembly":"demangle","processAssembly":"filter","backtrace":false}' -H "Referrer: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&code=$input_param" https://play.rust-lang.org/compile +} + +rust_playground_api_wasm_gist "$@"