diff --git a/jira/resources.py b/jira/resources.py index 29c86e604..d70c498db 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -11,6 +11,7 @@ import re import time from typing import TYPE_CHECKING, Any, cast +from urllib.parse import ParseResult, urlparse, urlunparse from requests import Response from requests.structures import CaseInsensitiveDict @@ -292,6 +293,24 @@ def _get_url(self, path: str) -> str: options.update({"path": path}) return self._base_url.format(**options) + def _validate_self_self_url(self) -> None: + """In the case of a proxy, use the configured option server URL.""" + if getattr(self, "self", None): + self.self: str + self_parsed = urlparse(self.self) + server_parsed = urlparse(self._options["server"]) + if self_parsed.netloc != server_parsed.netloc: + self.self = urlunparse( + ParseResult( + scheme=server_parsed.scheme, + netloc=server_parsed.netloc, + path=self_parsed.path, + params=self_parsed.params, + query=self_parsed.query, + fragment=self_parsed.fragment, + ) + ) + def update( self, fields: dict[str, Any] | None = None, @@ -326,6 +345,7 @@ def update( else: querystring = "" + self._validate_self_self_url() r = self._session.put(self.self + querystring, data=json.dumps(data)) if "autofix" in self._options and r.status_code == 400: user = None @@ -420,6 +440,7 @@ def delete(self, params: dict[str, Any] | None = None) -> Response | None: Returns: Optional[Response]: Returns None if async """ + self._validate_self_self_url() if self._options["async"]: # FIXME: mypy doesn't think this should work if not hasattr(self._session, "_async_jobs"): @@ -1504,7 +1525,7 @@ def __init__( session: ResilientSession, raw: dict[str, Any] | None = None, ): - self.self = None + self.self = "" Resource.__init__(self, path, options, session, self.AGILE_BASE_URL) if raw: diff --git a/tests/resources/test_issue.py b/tests/resources/test_issue.py index a496edb2e..27d3d67cd 100644 --- a/tests/resources/test_issue.py +++ b/tests/resources/test_issue.py @@ -337,6 +337,22 @@ def test_update_with_label(self): issue.update(fields=fields) self.assertEqual(issue.fields.labels, ["testLabel"]) + def test_update_label_with_proxy(self): + issue = self.jira.create_issue( + summary="Test issue for updating labels", + project=self.project_b, + description="Label testing", + issuetype=self.test_manager.CI_JIRA_ISSUE, + ) + + labelarray = ["testLabel"] + fields = {"labels": labelarray} + # This simulates when your Jira server is behind a proxy + # The self address returned will be different from the configured server + issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" + issue.update(fields=fields) + self.assertEqual(issue.fields.labels, ["testLabel"]) + def test_update_with_bad_label(self): issue = self.jira.create_issue( summary="Test issue for updating bad labels", @@ -373,6 +389,20 @@ def test_delete(self): issue.delete() self.assertRaises(JIRAError, self.jira.issue, key) + def test_delete_with_proxy(self): + issue = self.jira.create_issue( + summary="Test issue created", + project=self.project_b, + description="Not long for this world", + issuetype=self.test_manager.CI_JIRA_ISSUE, + ) + key = issue.key + # This simulates when your Jira server is behind a proxy + # The self address returned will be different from the configured server + issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" + issue.delete() + self.assertRaises(JIRAError, self.jira.issue, key) + def test_createmeta(self): meta = self.jira.createmeta() proj = find_by_key(meta["projects"], self.project_b)