From a3d8cec9f2c238ac6154105074af308f7045d235 Mon Sep 17 00:00:00 2001 From: Suleiman Dibirov Date: Mon, 11 Nov 2024 20:31:56 +0200 Subject: [PATCH] fix mockArchiveServer and refactor isRemoteHTTPArchive Signed-off-by: Suleiman Dibirov --- pkg/plugin/installer/http_installer_test.go | 13 ++++- pkg/plugin/installer/installer.go | 58 +++++++++++++-------- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/pkg/plugin/installer/http_installer_test.go b/pkg/plugin/installer/http_installer_test.go index 329841a24..75f6aee3a 100644 --- a/pkg/plugin/installer/http_installer_test.go +++ b/pkg/plugin/installer/http_installer_test.go @@ -25,6 +25,7 @@ import ( "net/http/httptest" "os" "path/filepath" + "sort" "strings" "syscall" "testing" @@ -67,8 +68,18 @@ func TestStripName(t *testing.T) { } func mockArchiveServer(extensionToContentType map[string]string) *httptest.Server { + // Extract and sort keys by length in descending order + extensions := make([]string, 0, len(extensionToContentType)) + for ext := range extensionToContentType { + extensions = append(extensions, ext) + } + sort.Slice(extensions, func(i, j int) bool { + return len(extensions[i]) > len(extensions[j]) + }) + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - for ext, contentType := range extensionToContentType { + for _, ext := range extensions { + contentType := extensionToContentType[ext] if strings.HasSuffix(r.URL.Path, ext) { w.Header().Add("Content-Type", contentType) fmt.Fprintln(w, "test") diff --git a/pkg/plugin/installer/installer.go b/pkg/plugin/installer/installer.go index 219f1c88c..6aeb4e2f2 100644 --- a/pkg/plugin/installer/installer.go +++ b/pkg/plugin/installer/installer.go @@ -94,37 +94,51 @@ func isLocalReference(source string) bool { // It works by checking whether the source looks like a URL and, if it does, running a // HEAD operation to see if the remote resource is a file that we understand. func isRemoteHTTPArchive(source string) bool { - if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") { - res, err := http.Head(source) - if err != nil { - // If we get an error at the network layer, we can't install it. So - // we return false. - return false - } - - // Next, we look for the content type or content disposition headers to see - // if they have matching extractors. - contentType := res.Header.Get("content-type") - var foundSuffix string + if !isHTTPURL(source) { + return false + } - if contentType == "application/octet-stream" { - foundSuffix = filepath.Ext(source) - } else { - foundSuffix, _ = mediaTypeToExtension(contentType) - } + contentType, err := getRemoteContentType(source) + if err != nil { + return false + } - if foundSuffix == "" { - // Media type not recognized - return false + // Handle octet-stream specially by checking file extension + if contentType == "application/octet-stream" { + for suffix := range Extractors { + if strings.HasSuffix(source, suffix) { + return true + } } - _, ok := Extractors[foundSuffix] + return false + } - return ok + // Check if we have an extractor for this media type + if suffix, ok := mediaTypeToExtension(contentType); ok { + _, hasExtractor := Extractors[suffix] + return hasExtractor } + return false } +// isHTTPURL checks if the source is an HTTP or HTTPS URL +func isHTTPURL(source string) bool { + return strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") +} + +// getRemoteContentType performs a HEAD request and returns the content-type +func getRemoteContentType(url string) (string, error) { + res, err := http.Head(url) + if err != nil { + return "", err + } + defer res.Body.Close() + + return res.Header.Get("content-type"), nil +} + // isPlugin checks if the directory contains a plugin.yaml file. func isPlugin(dirname string) bool { _, err := os.Stat(filepath.Join(dirname, plugin.PluginFileName))