From 37991585e7366fa1e10c5285d9c70721b85a5a7f Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 18 Jul 2025 08:24:02 -0500 Subject: [PATCH 1/6] support get requests --- src/main.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 906baf1..f403dca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -574,20 +574,21 @@ async fn main() -> Result<(), Box> { let request_start_time = time::Instant::now(); // Start timer // --- CHANGED: Support GET request type --- - if request_type == "GET" { - let req = client_client.get(&url_clone) - else if request_type == "POST" { + let req = if request_type == "GET" { + client_clone.get(&url_clone) + } else if request_type == "POST" { // --- CHANGED: Conditionally send POST with or without JSON --- let req = client_clone.post(&url_clone); - let req = if send_json_clone { + if send_json_clone { req.header("Content-Type", "application/json") .body(json_payload_clone.clone().unwrap()) } else { req - }; + } } else { eprintln!("Request type {} not currently supported", request_type); - } + client_clone.get(&url_clone) // fallback to GET + }; match req.send().await { Ok(response) => { From 1f28cfbcff4d6bb13b5c6b50515cfe150e8ebe7d Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 18 Jul 2025 08:28:22 -0500 Subject: [PATCH 2/6] 1. Syntax error: Missing semicolon and incorrect variable name client_client instead of client_clone 2. Ownership error: request_type was being moved into each async closure, so I added request_type_clone to properly clone it for each task 3. Variable usage: Updated all references within the async closure to use the cloned variables The fixes ensure that: - Each async task gets its own copy of the request_type string - The request building logic properly handles both GET and POST requests - The code compiles without ownership or syntax errors --- src/main.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index f403dca..ae066de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -545,6 +545,7 @@ async fn main() -> Result<(), Box> { let num_concurrent_tasks_clone = num_concurrent_tasks.clone(); let send_json_clone = send_json; let json_payload_clone = json_payload.clone(); + let request_type_clone = request_type.clone(); let handle = tokio::spawn(async move { loop { @@ -574,9 +575,9 @@ async fn main() -> Result<(), Box> { let request_start_time = time::Instant::now(); // Start timer // --- CHANGED: Support GET request type --- - let req = if request_type == "GET" { + let req = if request_type_clone == "GET" { client_clone.get(&url_clone) - } else if request_type == "POST" { + } else if request_type_clone == "POST" { // --- CHANGED: Conditionally send POST with or without JSON --- let req = client_clone.post(&url_clone); if send_json_clone { @@ -586,7 +587,7 @@ async fn main() -> Result<(), Box> { req } } else { - eprintln!("Request type {} not currently supported", request_type); + eprintln!("Request type {} not currently supported", request_type_clone); client_clone.get(&url_clone) // fallback to GET }; From f4cfe5e6896670add3f01d79519f7a06df3e3c93 Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 18 Jul 2025 08:32:12 -0500 Subject: [PATCH 3/6] adds the docker: prefix to explicitly tell syft to look for the image in the local Docker daemon rather than trying to pull it from a registry. This should resolve the "manifest unknown" error you're seeing. --- .github/workflows/build-cicd.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-cicd.yaml b/.github/workflows/build-cicd.yaml index da0fb4f..9d2598d 100644 --- a/.github/workflows/build-cicd.yaml +++ b/.github/workflows/build-cicd.yaml @@ -47,7 +47,7 @@ jobs: - name: Generate SBOM with Syft run: | syft --version - syft "cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}" -o cyclonedx-json > sbom.cyclonedx.json + syft "docker:cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}" -o cyclonedx-json > sbom.cyclonedx.json - name: Upload SBOM artifact uses: actions/upload-artifact@v4 From 4ac6888be3ff3a7eecf61bccc073934b49a89268 Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 18 Jul 2025 08:35:59 -0500 Subject: [PATCH 4/6] fix syft error --- .github/workflows/build-cicd.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-cicd.yaml b/.github/workflows/build-cicd.yaml index 9d2598d..20445ab 100644 --- a/.github/workflows/build-cicd.yaml +++ b/.github/workflows/build-cicd.yaml @@ -39,6 +39,7 @@ jobs: tags: cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }} provenance: true push: false + load: true - name: Install Syft run: | From 42ec4bdf1769d60391d166932b79b1e07564c368 Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 18 Jul 2025 08:37:09 -0500 Subject: [PATCH 5/6] fix syft error --- .github/workflows/build-cicd.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-cicd.yaml b/.github/workflows/build-cicd.yaml index 20445ab..24e9d32 100644 --- a/.github/workflows/build-cicd.yaml +++ b/.github/workflows/build-cicd.yaml @@ -37,7 +37,6 @@ jobs: file: ./Dockerfile platforms: linux/amd64 tags: cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }} - provenance: true push: false load: true From e4f373888173e6600b2f9f0845d8e7667f7956c1 Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 18 Jul 2025 08:43:14 -0500 Subject: [PATCH 6/6] update README.md --- README.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f099b3c..ceecb70 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ The load testing tool is configured primarily through environment variables pass ### Common Environment Variables * TARGET_URL (Required): The full URL of the endpoint you want to load test (e.g., http://example.com/api/data or https://secure-api.com/status). +* REQUEST_TYPE (Optional, default: POST): The HTTP method to use for requests. Supported values are "GET" and "POST". * NUM_CONCURRENT_TASKS (Optional, default: 10): The maximum number of concurrent HTTP requests (worker tasks) that the load generator will attempt to maintain. This acts as a concurrency limit. * TEST_DURATION (Optional, default: 2h): The total duration for which the load test will run. Accepts values like 10m (10 minutes), 1h (1 hour), 3d (3 days). * SKIP_TLS_VERIFY (Optional, default: false): Set to "true" to skip TLS/SSL certificate verification for HTTPS endpoints. Use with caution, primarily for testing environments with self-signed certificates. @@ -155,20 +156,51 @@ docker run --rm \ cbaugus/rust-loadtester:latest ``` -### Sending a JSON Payload (e.g., for Login Endpoints) +### Choosing Request Type (GET vs POST) + +You can configure the tool to send either GET or POST requests using the `REQUEST_TYPE` environment variable: + +* `REQUEST_TYPE` (Optional, default: POST): Set to `"GET"` for GET requests or `"POST"` for POST requests. + +**Example with GET requests:** + +```bash +docker run --rm \ + -e TARGET_URL="https://jsonplaceholder.typicode.com/posts/1" \ + -e REQUEST_TYPE="GET" \ + -e NUM_CONCURRENT_TASKS="50" \ + -e TEST_DURATION="5m" \ + -e LOAD_MODEL_TYPE="Concurrent" \ + cbaugus/rust-loadtester:latest +``` + +**Example with POST requests (default):** + +```bash +docker run --rm \ + -e TARGET_URL="https://your-service.com/api/data" \ + -e REQUEST_TYPE="POST" \ + -e NUM_CONCURRENT_TASKS="50" \ + -e TEST_DURATION="5m" \ + -e LOAD_MODEL_TYPE="Concurrent" \ + cbaugus/rust-loadtester:latest +``` + +### Sending a JSON Payload (for POST requests) You can configure the tool to send a JSON body with each POST request (for example, to test login endpoints that expect a JSON payload). This is controlled by two environment variables: * `SEND_JSON` (Optional, default: false): Set to `"true"` to enable sending a JSON payload in the body of each POST request. * `JSON_PAYLOAD` (Required if `SEND_JSON=true`): The JSON string to send as the request body. -If `SEND_JSON` is not set or is not `"true"`, requests will be sent without a body. +If `SEND_JSON` is not set or is not `"true"`, POST requests will be sent without a body. Note that JSON payloads are only sent with POST requests, not GET requests. **Example:** ```bash docker run --rm \ -e TARGET_URL="https://your-service.com/login" \ + -e REQUEST_TYPE="POST" \ -e SEND_JSON="true" \ -e JSON_PAYLOAD='{"username":"testuser","password":"testpass"}' \ -e NUM_CONCURRENT_TASKS="20" \