summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Wittig <max.wittig@siemens.com>2022-08-04 16:36:31 +0200
committerGitHub <noreply@github.com>2022-08-04 16:36:31 +0200
commitd263f57a34a58d44531e3abbdbfedf354b0c70ca (patch)
tree767a6ffd18128fe96108836cc3de714bd672a36d
parent2ebfc7096ddbf2386029536acef1858985f3f257 (diff)
parent1398426cd748fdf492fe6184b03ac2fcb7e4fd6e (diff)
downloadgitlab-d263f57a34a58d44531e3abbdbfedf354b0c70ca.tar.gz
Merge pull request #2219 from python-gitlab/fix/no-duplicate-params
fix(client): ensure encoded query params are never duplicated
-rw-r--r--gitlab/client.py9
-rw-r--r--tests/unit/test_gitlab_http_methods.py18
2 files changed, 25 insertions, 2 deletions
diff --git a/gitlab/client.py b/gitlab/client.py
index dc6b6e6..b3223e5 100644
--- a/gitlab/client.py
+++ b/gitlab/client.py
@@ -20,6 +20,7 @@ import os
import re
import time
from typing import Any, cast, Dict, List, Optional, Tuple, TYPE_CHECKING, Union
+from urllib import parse
import requests
import requests.utils
@@ -677,11 +678,15 @@ class Gitlab:
GitlabHttpError: When the return code is not 2xx
"""
query_data = query_data or {}
- url = self._build_url(path)
+ raw_url = self._build_url(path)
- params: Dict[str, Any] = {}
+ # parse user-provided URL params to ensure we don't add our own duplicates
+ parsed = parse.urlparse(raw_url)
+ params = parse.parse_qs(parsed.query)
utils.copy_dict(src=query_data, dest=params)
+ url = raw_url.replace(parsed.query, "").strip("?")
+
# Deal with kwargs: by default a user uses kwargs to send data to the
# gitlab server, but this generates problems (python keyword conflicts
# and python-gitlab/gitlab conflicts).
diff --git a/tests/unit/test_gitlab_http_methods.py b/tests/unit/test_gitlab_http_methods.py
index 3d5a3fb..252ecb6 100644
--- a/tests/unit/test_gitlab_http_methods.py
+++ b/tests/unit/test_gitlab_http_methods.py
@@ -37,6 +37,24 @@ def test_http_request(gl):
@responses.activate
+def test_http_request_with_url_encoded_kwargs_does_not_duplicate_params(gl):
+ url = "http://localhost/api/v4/projects?topics%5B%5D=python"
+ responses.add(
+ method=responses.GET,
+ url=url,
+ json=[{"name": "project1"}],
+ status=200,
+ match=[responses.matchers.query_param_matcher({"topics[]": "python"})],
+ )
+
+ kwargs = {"topics[]": "python"}
+ http_r = gl.http_request("get", "/projects?topics%5B%5D=python", **kwargs)
+ http_r.json()
+ assert http_r.status_code == 200
+ assert responses.assert_call_count(url, 1)
+
+
+@responses.activate
def test_http_request_404(gl):
url = "http://localhost/api/v4/not_there"
responses.add(