From 30b7cef026fd6ebdb1aa1e9ba4e30d2219ed8276 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sat, 27 Jun 2026 08:02:52 +1000 Subject: [PATCH] fix: strip base URL path prefix from helm chart download URLs (#64) When a helm repo base URL includes a path component (e.g. \`stakater.github.io/stakater-charts\`), the merger was extracting the full URL path (\`stakater-charts/reloader-2.2.8.tgz\`) and the proxy then constructed \`base_url/stakater-charts/reloader-2.2.8.tgz\` = double path = 404. Fix: \`extractPathRelativeToBase()\` strips the shared base path prefix so only the filename portion is used as the proxy path. Reviewed-on: https://git.unkin.net/unkin/artifactapi/pulls/64 Co-authored-by: Ben Vincent Co-committed-by: Ben Vincent --- internal/virtual/helm_merger.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/virtual/helm_merger.go b/internal/virtual/helm_merger.go index db1d206..94641d7 100644 --- a/internal/virtual/helm_merger.go +++ b/internal/virtual/helm_merger.go @@ -65,11 +65,12 @@ func (m *HelmMerger) MergeIndexes(members []MemberIndex, proxyBaseURL string) ([ if baseHost != "" && extractHost(u) != baseHost { continue } + relPath := extractPathRelativeToBase(u, member.BaseURL) ver.URLs[i] = fmt.Sprintf("%s/api/v1/%s/%s/%s", strings.TrimRight(proxyBaseURL, "/"), routePrefix, member.RemoteName, - extractPath(u)) + relPath) } else { ver.URLs[i] = fmt.Sprintf("%s/api/v1/%s/%s/%s", strings.TrimRight(proxyBaseURL, "/"), @@ -102,6 +103,18 @@ func extractHost(rawURL string) string { return rest[:slashIdx] } +func extractPathRelativeToBase(rawURL, baseURL string) string { + fullPath := extractPath(rawURL) + basePath := extractPath(baseURL) + if basePath != "" { + basePath = strings.TrimRight(basePath, "/") + "/" + if strings.HasPrefix(fullPath, basePath) { + return fullPath[len(basePath):] + } + } + return fullPath +} + func extractPath(rawURL string) string { idx := strings.Index(rawURL, "://") if idx == -1 {