[go: up one dir, main page]

Skip to content

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
Edited by 🤖 GitLab Bot 🤖