-
Notifications
You must be signed in to change notification settings - Fork 675
Description
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