From c595edccac99fc237071a9e7f78dd4349ffc3c38 Mon Sep 17 00:00:00 2001 From: Fabio Bonelli Date: Tue, 10 Nov 2026 05:57:35 +0000 Subject: [PATCH] fix: bound publisher list downloads --- cmd/download_publishers.go | 18 ++++++++++++++---- cmd/download_publishers_test.go | 30 +++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/cmd/download_publishers.go b/cmd/download_publishers.go index 24016d0..1a48e08 100644 --- a/cmd/download_publishers.go +++ b/cmd/download_publishers.go @@ -7,12 +7,22 @@ import ( "net/http" "net/url" "os" + "time" "github.com/italia/publiccode-crawler/v4/common" "github.com/spf13/cobra" "gopkg.in/yaml.v3" ) +const publisherDownloadTimeout = 30 * time.Second + +var publisherDownloadHTTPClient = &http.Client{ + Transport: nil, + CheckRedirect: nil, + Jar: nil, + Timeout: publisherDownloadTimeout, +} + func init() { rootCmd.AddCommand(downloadPublishersCmd) } @@ -34,11 +44,11 @@ var downloadPublishersCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - return downloadPublishers(args[0], args[1]) + return downloadPublishers(context.Background(), args[0], args[1]) }, } -func downloadPublishers(repolistURL, destination string) error { +func downloadPublishers(ctx context.Context, repolistURL, destination string) error { var publishers []common.Publisher if _, err := os.Stat(destination); err == nil { @@ -50,12 +60,12 @@ func downloadPublishers(repolistURL, destination string) error { _ = yaml.Unmarshal(data, &publishers) } - request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, repolistURL, nil) + request, err := http.NewRequestWithContext(ctx, http.MethodGet, repolistURL, nil) if err != nil { return err } - resp, err := http.DefaultClient.Do(request) + resp, err := publisherDownloadHTTPClient.Do(request) if err != nil { return err } diff --git a/cmd/download_publishers_test.go b/cmd/download_publishers_test.go index 5d80339..333035c 100644 --- a/cmd/download_publishers_test.go +++ b/cmd/download_publishers_test.go @@ -1,14 +1,24 @@ package cmd import ( + "context" "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" + "time" ) +func TestPublisherDownloadClientSetsTimeout(t *testing.T) { + t.Parallel() + + if publisherDownloadHTTPClient.Timeout != publisherDownloadTimeout { + t.Fatalf("publisherDownloadHTTPClient.Timeout = %s, want %s", publisherDownloadHTTPClient.Timeout, publisherDownloadTimeout) + } +} + func TestDownloadPublishersKeepsDestinationOnUnsuccessfulResponse(t *testing.T) { t.Parallel() @@ -23,7 +33,7 @@ func TestDownloadPublishersKeepsDestinationOnUnsuccessfulResponse(t *testing.T) t.Fatal(err) } - err := downloadPublishers(server.URL, destination) + err := downloadPublishers(context.Background(), server.URL, destination) if err == nil { t.Fatal("downloadPublishers() returned nil error") } @@ -39,3 +49,21 @@ func TestDownloadPublishersKeepsDestinationOnUnsuccessfulResponse(t *testing.T) t.Fatalf("destination = %q, want %q", data, original) } } + +func TestDownloadPublishersCancelsStalledResponse(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { + <-r.Context().Done() + })) + t.Cleanup(server.Close) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + err := downloadPublishers(ctx, server.URL, t.TempDir()+"/publishers.yml") + if err == nil { + t.Fatal("downloadPublishers() returned nil error") + } + if !strings.Contains(err.Error(), "context deadline exceeded") { + t.Fatalf("downloadPublishers() error = %v, want context deadline exceeded", err) + } +}