Skip to content

Redirects with dot in project name do not resolve correctly and raise 404 error instead #3299

@uglybug

Description

@uglybug

Redirects for projects with dot in name do not resolve correctly

When a request is made to GitLab for a project that will be redirected to a new path (HTTP 302 response), a quirk with GitLab's API is that the path_with_namespace passed to https://gitlab.com/api/vi/projects/{encoded_path_with_namespace} needs to have any dots encoded to %2E in order for the Location in the response header to be correct. Although this seems to be a "bug" with GitLab itself, this package could easily work around it by replacing dots with %2E which then makes everything work fine.

We can demonstrate this pretty simply with the following code, using a project I created and then renamed to demonstrate this behaviour:

import gitlab
gl = gitlab.Gitlab("https://gitlab.com")
gl.projects.get("simon.burton1/redirect.test")

Which causes:

gitlab.exceptions.GitlabGetError: 404: 404 Project Not Found

We can see why this is happening by repeating the same with curl. First by doing exactly what python-gitlab is doing in EncodedId doing by using the url encoded fragment, as urllib.parse.quote would return with safe="":

curl --request GET --url "https://gitlab.com/api/v4/projects/simon.burton1%2Fredirect.test"
This resource has been moved permanently to https://gitlab.com/api/v4/projects/76187413.test

Note the erroneous .test that is added to the redirect message by GitLab. And checking the response headers, we can see that the Location does indeed get this erroneous url, which will cause any redirect to ultimately 404, as that path obviously does not exist:

< location: https://gitlab.com/api/v4/projects/76187413.test

However, if we encode the dots in the project path, as well as the slashes:

curl --request GET --url "https://gitlab.com/api/v4/projects/simon%2Eburton1%2Fredirect%2Etest"
This resource has been moved permanently to https://gitlab.com/api/v4/projects/76187413

And we can see that the redirect location header is indeed correct:

< location: https://gitlab.com/api/v4/projects/76187413

We can validate that this is not a more general issue with API redirects and is limited to this behaviour with dots, by requesting another redirected project that doesn't have dots in the path_with_namespace, thus:

gl.projects.get("gitlab-org/gitlab-ce")
<Project id:13083 path_with_namespace:gitlab-org/gitlab-foss>

Expected Behaviour

python-gitlab should encode any dots in Gitlab.projects.get as %2E to work around the probable bug in GitLab's own API, so that projects.get("redirected.project") will return the new project.

Although one could argue that this is a bug in GitLab, which may or may not be the case, it's not actually documented about how these paths should be encoded, just that they should be "url encoded" (https://docs.gitlab.com/api/rest/#namespaced-paths), and encoding dots is not "wrong", per se. Just usually unnecessary.

Secondly, we know that even if it were a bug in GitLab's API, they won't fix it for 7 years, and the workaround in python-gitlab would be both a valid url encoding anyway, and would enable users of this package to be redirected correctly when requesting moved projects with dots in their namespaced paths.

Actual Behaviour

A 404 error is returned for an otherwise resolvable redirect when projects.get("redirected.project") is called with a dot in the project path, as per this example.

Suggested Fix

In gitlab.utils.EncodedId.__new__(), updating this line works in this case, but I haven't tested whether this has any knock-on effect for anything else that calls this encoder, so I haven't raised a PR as I cannot prove that there are not regressions without more time to test. Happy to raise a PR though, if you would prefer that:

248        if isinstance(value, str):
249            value = urllib.parse.quote(value, safe="").replace(".", "%2E")

Specifications

  • python-gitlab version: 7.0.0
  • Gitlab server version (or gitlab.com): gitlab.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions