From 1883d62cc66a8f5fb4b02279c165d8f2e1bead0d Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Fri, 13 Jun 2025 17:51:31 +0300 Subject: [PATCH] Add rate limiting --- go.mod | 2 ++ go.sum | 2 ++ main.go | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 go.sum diff --git a/go.mod b/go.mod index 9b7d059..dfe65d1 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module imgdownloader go 1.24.3 + +require golang.org/x/time v0.12.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..457536c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= diff --git a/main.go b/main.go index 70bc99a..d8ed9de 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "flag" "fmt" @@ -10,15 +11,21 @@ import ( "path/filepath" "sync" "time" + + "golang.org/x/time/rate" ) // HTTP клиент с таймаутом var httpClient *http.Client +// Глобальный rate limiter +var limiter *rate.Limiter + func main() { timeout := flag.Duration("t", 60*time.Second, "request timeout") retries := flag.Int("r", 5, "number of download attempts") jobs := flag.Int("j", 5, "concurrent downloads") + rateLimit := flag.Float64("rate", 0, "maximum downloads per second (0 = no limit)") flag.Parse() @@ -36,6 +43,11 @@ func main() { Timeout: *timeout, } + // Инициализируем rate limiter + if *rateLimit > 0 { + limiter = rate.NewLimiter(rate.Limit(*rateLimit), 1) + } + // Создаем директорию для загрузок if err := os.MkdirAll(outputDir, 0755); err != nil { fmt.Printf("Error creating directory: %v\n", err) @@ -128,6 +140,13 @@ func downloadImage(url, filename string, maxRetries int) error { // Одна попытка скачивания func attemptDownload(url, filename string) error { + // Применяем rate limiting если он включен + if limiter != nil { + if err := limiter.Wait(context.Background()); err != nil { + return fmt.Errorf("rate limiter error: %v", err) + } + } + resp, err := httpClient.Get(url) if err != nil { return err