Redirects for moved projects drops the requested archive file format (defaulting to TAR)
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
When using the Repository API archive download endpoint, making a request to download a ZIP archive for a project that has been moved (e.g. from group-1/project
to group-2/subproject/project
) using its URL-encoded path as the :id
will return a TAR file instead.
This happens because Gitlab will 301 redirect:
- The original path:
/projects/group-1%2Fproject/repository/archive.zip
- To the new path:
/projects/<n>/repository/archive
Notice the stripped .zip
format extension. Without this [.format]
portion of the path, Gitlab then defaults to returning a TAR archive.
This is especially important since these paths are hard-coded in lockfiles like composer.lock
. Composer will make this API call expecting a ZIP, but silently receiving a TAR, and unzip
will catastrophically fail. This means moving a project can bring down unrelated work downstream when caches are invalidated, requiring manual intervention to composer update --lock
to refresh any out-of-date distributable URLs.
Redacted Demo:
Click to expand
❯ wget --header="Private-Token: REDACTED" https://gitlab.private.com/api/v4/projects/group-1%2Fproject/repository/archive.zip
--2024-09-10 14:12:14-- https://gitlab.private.com/api/v4/projects/group-2%2Fsubgroup%2Fproject/repository/archive.zip
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
Resolving gitlab.private.com (gitlab.private.com)... XXX.XXX.XXX.XXX
Connecting to gitlab.private.com (gitlab.private.com)|XXX.XXX.XXX.XXX|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://gitlab.private.com/api/v4/projects/NNN/repository/archive [following]
--2024-09-10 14:12:14-- https://gitlab.private.com/api/v4/projects/NNN/repository/archive
Reusing existing connection to gitlab.private.com:443.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/octet-stream]
Saving to: ‘archive.zip’
archive.zip [ <=> ] 16.17K --.-KB/s in 0.03s
2024-09-10 14:12:14 (534 KB/s) - ‘archive.zip’ saved [16553]
❯ file archive.zip
archive.zip: gzip compressed data, from Unix, original size modulo 2^32 143360
❯ unzip archive.zip
Archive: archive.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of archive.zip or
archive.zip.zip, and cannot find archive.zip.ZIP, period.
To be clear, using the current URL-encoded path of a project does not suffer the same issue:
Click to expand
❯ wget --header="Private-Token: REDACTED" https://gitlab.private.com/api/v4/projects/group-2%2Fsubgroup%2Fproject/repository/archive.zip
--2024-09-10 14:18:34-- https://gitlab.private.com/api/v4/projects/group-2%2Fsubgroup%2Fproject/repository/archive.zip
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
Resolving gitlab.private.com (gitlab.private.com)... XXX.XXX.XXX.XXX
Connecting to gitlab.private.com (gitlab.private.com)|XXX.XXX.XXX.XXX|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘archive.zip.1’
archive.zip.1 [ <=> ] 27.09K --.-KB/s in 0.03s
2024-09-10 14:18:34 (891 KB/s) - ‘archive.zip.1’ saved [27736]
❯ file archive.zip.1
archive.zip.1: Zip archive data, at least v1.0 to extract, compression method=store