From c41575710ef9ccc04a04391e570f383b1d174942 Mon Sep 17 00:00:00 2001 From: Gareth Rushgrove Date: Wed, 11 Oct 2023 09:25:25 +0100 Subject: [PATCH] Fix issue with limit duplication leading to errors [this commit](https://github.com/snyk-labs/pysnyk/commit/dc75bc926aa369d7d39e89e744b3b07d6af0fb0f) introduced a default limit in the client. However, the limit is also present in the URL. That leads to the 2nd and subsequent pages failing due to passing `limit=X&limit=X`. That is interpreted as an array by the server, and will fail with a client error. The fix checks the URL for the limit, and avoids the duplication if present. --- snyk/client.py | 6 ++++++ snyk/managers.py | 4 +--- snyk/test_client.py | 7 +++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/snyk/client.py b/snyk/client.py index 8665ae0..e3fa329 100644 --- a/snyk/client.py +++ b/snyk/client.py @@ -1,6 +1,7 @@ import logging import urllib.parse from typing import Any, List, Optional +from urllib.parse import parse_qs, urlparse import requests from retry.api import retry_call @@ -162,6 +163,11 @@ def get( if isinstance(v, bool): params[k] = str(v).lower() + # the limit is returned in the url, and if two limits are passed + # the API interprets as an array and throws an error + if "limit" in parse_qs(urlparse(path).query): + params.pop("limit", None) + debug_url = f"{url}&{urllib.parse.urlencode(params)}" fkwargs = {"headers": self.api_headers, "params": params} else: diff --git a/snyk/managers.py b/snyk/managers.py index 0d59233..e7bafd5 100644 --- a/snyk/managers.py +++ b/snyk/managers.py @@ -191,9 +191,7 @@ def _rest_to_v1_response_format(self, project): def _query(self, tags: List[Dict[str, str]] = [], next_url: str = None): projects = [] - params: dict = { - "limit": 100, - } + params: dict = {"limit": 100} if self.instance: path = "/orgs/%s/projects" % self.instance.id if not next_url else next_url diff --git a/snyk/test_client.py b/snyk/test_client.py index f97ab97..ec0bb93 100644 --- a/snyk/test_client.py +++ b/snyk/test_client.py @@ -322,3 +322,10 @@ def test_get_rest_pages( data = rest_client.get_rest_pages(f"orgs/{V3_ORG}/targets", t_params) assert len(data) == 30 + + def test_rest_limit_deduplication(self, requests_mock, rest_client): + requests_mock.get( + f"{REST_URL}/orgs/{REST_ORG}/projects?limit=100&version={REST_VERSION}" + ) + params = {"limit": 10} + rest_client.get(f"orgs/{REST_ORG}/projects?limit=100", params)