package httpdl import ( "context" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "github.com/hanbok/got/download" ) // TestConditionalGet304 checks that --conditional-get sends If-Modified-Since // for an existing local file and treats a 304 as success without rewriting the // file. func TestConditionalGet304(t *testing.T) { dir := t.TempDir() out := filepath.Join(dir, "file.bin") const existing = "already here" if err := os.WriteFile(out, []byte(existing), 0o644); err != nil { t.Fatal(err) } gotIfModSince := false srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("If-Modified-Since") != "" { gotIfModSince = true } w.WriteHeader(http.StatusNotModified) })) defer srv.Close() d := New([]string{srv.URL + "/file.bin"}, Config{ Dir: dir, Out: "file.bin", MaxConnPerServer: 1, ConditionalGet: true, AllowOverwrite: true, UserAgent: "got-test", }) if err := d.Run(context.Background()); err != nil { t.Fatalf("conditional-get 304 should succeed, got %v", err) } if !gotIfModSince { t.Fatal("expected an If-Modified-Since header on the request") } if d.Stat().Status != download.Complete { t.Fatalf("status = %v, want Complete", d.Stat().Status) } // The file must be untouched: 304 means "up to date". b, err := os.ReadFile(out) if err != nil { t.Fatal(err) } if string(b) != existing { t.Fatalf("file was rewritten: %q, want %q", b, existing) } } // TestConditionalGetSkippedWithControlFile verifies the rule that // --conditional-get is ignored when a .got control file exists, so an // in-progress resume is never short-circuited by a 304. func TestConditionalGetSkippedWithControlFile(t *testing.T) { dir := t.TempDir() out := filepath.Join(dir, "file.bin") if err := os.WriteFile(out, []byte("partial"), 0o644); err != nil { t.Fatal(err) } // A control file present means a resume is in flight. if err := os.WriteFile(controlPath(out), []byte("{}"), 0o644); err != nil { t.Fatal(err) } sawIfModSince := false srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("If-Modified-Since") != "" { sawIfModSince = true } // Serve a small body so the run can complete. http.Error(w, "no range", http.StatusOK) })) defer srv.Close() d := New([]string{srv.URL + "/file.bin"}, Config{ Dir: dir, Out: "file.bin", MaxConnPerServer: 1, ConditionalGet: true, AllowOverwrite: true, UserAgent: "got-test", }) _ = d.Run(context.Background()) if sawIfModSince { t.Fatal("If-Modified-Since must not be sent when a control file exists") } }