Ensure that we never download "legacy" archive formats

The `zipball_url` and `tarball_url` fields on the Release API payload
always link to "legacy" archives that are of a different format than
those one would get if they downloaded an archive from a Release using
the web interface. The GitHub API does not seem to publish links to
non-legacy archives.

This adds a redirect hack to turn "legacy" Codeload URLs into non-legacy
ones with the goal of ensuring the consistency of user experience when
downloading archives.
This commit is contained in:
Mislav Marohnić 2021-11-30 15:33:06 +01:00
parent 8058c4ea34
commit 8e311847db

View file

@ -8,6 +8,7 @@ import (
"net/http"
"os"
"path/filepath"
"regexp"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/api"
@ -228,9 +229,19 @@ func downloadAsset(httpClient *http.Client, assetURL, destinationDir string, fil
}
req.Header.Set("Accept", "application/octet-stream")
// adding application/json to Accept header due to a bug in the zipball/tarball API endpoint that makes it mandatory
if isArchive {
// adding application/json to Accept header due to a bug in the zipball/tarball API endpoint that makes it mandatory
req.Header.Set("Accept", "application/octet-stream, application/json")
// override HTTP redirect logic to avoid "legacy" Codeload resources
oldClient := *httpClient
httpClient = &oldClient
httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
if len(via) == 1 {
req.URL.Path = removeLegacyFromCodeloadPath(req.URL.Path)
}
return nil
}
}
resp, err := httpClient.Do(req)
@ -268,3 +279,16 @@ func downloadAsset(httpClient *http.Client, assetURL, destinationDir string, fil
_, err = io.Copy(f, resp.Body)
return err
}
var codeloadLegacyRE = regexp.MustCompile(`^(/[^/]+/[^/]+/)legacy\.`)
// removeLegacyFromCodeloadPath converts URLs for "legacy" Codeload archives into ones that match the format
// when you choose to download "Source code (zip/tar.gz)" from a tagged release on the web. The legacy URLs
// look like this:
//
// https://codeload.github.com/OWNER/REPO/legacy.zip/refs/tags/TAGNAME
//
// Removing the "legacy." part results in a valid Codeload URL for our desired archive format.
func removeLegacyFromCodeloadPath(p string) string {
return codeloadLegacyRE.ReplaceAllString(p, "$1")
}