diff --git a/internal/httpapi/packages.go b/internal/httpapi/packages.go index 922518d..86680dc 100644 --- a/internal/httpapi/packages.go +++ b/internal/httpapi/packages.go @@ -235,8 +235,12 @@ func (s *Server) download(writer http.ResponseWriter, request *http.Request, nam } defer file.Close() target := item.Targets[0] + fileName := filepath.Base(strings.TrimSpace(target.FileName)) + if err := registry.ValidateFileName(fileName); err != nil { + fileName = fmt.Sprintf("%s-%s.pkg", name, version) + } writer.Header().Set("Content-Type", "application/octet-stream") - writer.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, target.FileName)) + writer.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName)) writer.Header().Set("X-Scout-SHA256", target.SHA256) writer.Header().Set("X-Scout-Platform", target.Platform) writer.Header().Set("X-Scout-Architecture", target.Architecture) diff --git a/internal/httpapi/server_test.go b/internal/httpapi/server_test.go index d78f903..cfedacc 100644 --- a/internal/httpapi/server_test.go +++ b/internal/httpapi/server_test.go @@ -8,7 +8,10 @@ import ( "net/http" "net/http/httptest" "net/url" + "os" + "path/filepath" "testing" + "time" "scout/internal/registry" ) @@ -96,6 +99,49 @@ func TestUploadListLatestAndDownload(t *testing.T) { } } +func TestDownloadUsesFallbackFileNameForLegacyPackage(t *testing.T) { + root := t.TempDir() + versionDir := filepath.Join(root, "legacy-demo", "1.0.0") + if err := os.MkdirAll(versionDir, 0o755); err != nil { + t.Fatal(err) + } + legacy := registry.Package{ + Name: "legacy-demo", + Version: "1.0.0", + Status: "published", + Size: 6, + UploadedAt: time.Now().UTC(), + } + metadata, err := json.Marshal(legacy) + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(versionDir, "metadata.json"), metadata, 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(versionDir, "package.bin"), []byte("legacy"), 0o644); err != nil { + t.Fatal(err) + } + store, err := registry.New(root) + if err != nil { + t.Fatal(err) + } + server := httptest.NewServer((&Server{Registry: store}).Handler()) + defer server.Close() + + response, err := http.Get(server.URL + "/api/v1/packages/legacy-demo/1.0.0/download") + if err != nil { + t.Fatal(err) + } + defer response.Body.Close() + if response.StatusCode != http.StatusOK { + t.Fatalf("历史包下载状态错误: %d", response.StatusCode) + } + if got := response.Header.Get("Content-Disposition"); got != `attachment; filename="legacy-demo-1.0.0.pkg"` { + t.Fatalf("历史包下载文件名错误: %s", got) + } +} + func TestStreamFiltersPackage(t *testing.T) { store, err := registry.New(t.TempDir()) if err != nil {