Files
zcli-playground/ddosbot/main.go
T
2026-02-08 10:25:39 +01:00

96 lines
2.0 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"os"
"strings"
"sync"
"sync/atomic"
"time"
)
func main() {
// Read URLs from environment variable
urlsEnv := os.Getenv("TARGET_URLS")
if urlsEnv == "" {
log.Fatal("TARGET_URLS environment variable is not set")
}
// Parse comma-delimited URLs
urls := strings.Split(urlsEnv, ",")
for i := range urls {
urls[i] = strings.TrimSpace(urls[i])
}
if len(urls) == 0 {
log.Fatal("No URLs provided")
}
fmt.Printf("Starting load test on %d URLs\n", len(urls))
fmt.Println("URLs:", urls)
fmt.Println("Press Ctrl+C to stop\n")
// Counters
var (
totalRequests uint64
successCount uint64
errorCount uint64
)
// WaitGroup to track all goroutines
var wg sync.WaitGroup
// Start time
startTime := time.Now()
// Spawn a goroutine for each URL
for _, url := range urls {
wg.Add(1)
go func(targetURL string) {
defer wg.Done()
client := &http.Client{Timeout: time.Second}
for {
resp, err := client.Get(targetURL)
atomic.AddUint64(&totalRequests, 1)
if err != nil {
fmt.Printf("error: %s => %v\n", targetURL, err)
atomic.AddUint64(&errorCount, 1)
continue
}
_ = resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
atomic.AddUint64(&successCount, 1)
} else {
fmt.Printf("bad status: %s => %d\n", targetURL, resp.StatusCode)
atomic.AddUint64(&errorCount, 1)
}
}
}(url)
}
// Progress reporter
go func() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
<-ticker.C
elapsed := time.Since(startTime).Seconds()
requests := atomic.LoadUint64(&totalRequests)
success := atomic.LoadUint64(&successCount)
errors := atomic.LoadUint64(&errorCount)
fmt.Printf("Elapsed: %.0fs | Requests: %d | Success: %d | Errors: %d | Rate: %.0f req/s\n",
elapsed, requests, success, errors, float64(requests)/elapsed)
}
}()
// Wait for all goroutines (runs forever until killed)
wg.Wait()
}