summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Cloke <clokep@users.noreply.github.com>2024-03-08 04:33:46 -0500
committerGitHub <noreply@github.com>2024-03-08 09:33:46 +0000
commit696cc9e802f63ba8657856d85f6982f49de14f27 (patch)
treedd704c2abb3865fd788968c97de147044ead6e8d
parentFix joining remote rooms when a `on_new_event` callback is registered (#16973) (diff)
downloadsynapse-696cc9e802f63ba8657856d85f6982f49de14f27.tar.xz
Stabilize support for Retry-After header (MSC4014) (#16947)
-rw-r--r--changelog.d/16947.feature1
-rw-r--r--synapse/api/errors.py5
-rw-r--r--synapse/config/experimental.py9
-rw-r--r--tests/api/test_errors.py8
-rw-r--r--tests/rest/client/test_login.py3
5 files changed, 5 insertions, 21 deletions
diff --git a/changelog.d/16947.feature b/changelog.d/16947.feature
new file mode 100644
index 0000000000..efd0dbddb2
--- /dev/null
+++ b/changelog.d/16947.feature
@@ -0,0 +1 @@
+Include `Retry-After` header by default per [MSC4041](https://github.com/matrix-org/matrix-spec-proposals/pull/4041). Contributed by @clokep.
diff --git a/synapse/api/errors.py b/synapse/api/errors.py
index b44088f9b3..dd4a1ae706 100644
--- a/synapse/api/errors.py
+++ b/synapse/api/errors.py
@@ -517,8 +517,6 @@ class InvalidCaptchaError(SynapseError):
 class LimitExceededError(SynapseError):
     """A client has sent too many requests and is being throttled."""
 
-    include_retry_after_header = False
-
     def __init__(
         self,
         limiter_name: str,
@@ -526,9 +524,10 @@ class LimitExceededError(SynapseError):
         retry_after_ms: Optional[int] = None,
         errcode: str = Codes.LIMIT_EXCEEDED,
     ):
+        # Use HTTP header Retry-After to enable library-assisted retry handling.
         headers = (
             {"Retry-After": str(math.ceil(retry_after_ms / 1000))}
-            if self.include_retry_after_header and retry_after_ms is not None
+            if retry_after_ms is not None
             else None
         )
         super().__init__(code, "Too Many Requests", errcode, headers=headers)
diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py
index d43d9da956..0bd3befdc2 100644
--- a/synapse/config/experimental.py
+++ b/synapse/config/experimental.py
@@ -25,7 +25,6 @@ from typing import TYPE_CHECKING, Any, Optional
 import attr
 import attr.validators
 
-from synapse.api.errors import LimitExceededError
 from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersions
 from synapse.config import ConfigError
 from synapse.config._base import Config, RootConfig
@@ -415,14 +414,6 @@ class ExperimentalConfig(Config):
             "msc4010_push_rules_account_data", False
         )
 
-        # MSC4041: Use HTTP header Retry-After to enable library-assisted retry handling
-        #
-        # This is a bit hacky, but the most reasonable way to *alway* include the
-        # headers.
-        LimitExceededError.include_retry_after_header = experimental.get(
-            "msc4041_enabled", False
-        )
-
         self.msc4028_push_encrypted_events = experimental.get(
             "msc4028_push_encrypted_events", False
         )
diff --git a/tests/api/test_errors.py b/tests/api/test_errors.py
index 25fa93b9d8..efa3addf00 100644
--- a/tests/api/test_errors.py
+++ b/tests/api/test_errors.py
@@ -33,18 +33,14 @@ class LimitExceededErrorTestCase(unittest.TestCase):
         self.assertIn("needle", err.debug_context)
         self.assertNotIn("needle", serialised)
 
-    # Create a sub-class to avoid mutating the class-level property.
-    class LimitExceededErrorHeaders(LimitExceededError):
-        include_retry_after_header = True
-
     def test_limit_exceeded_header(self) -> None:
-        err = self.LimitExceededErrorHeaders(limiter_name="test", retry_after_ms=100)
+        err = LimitExceededError(limiter_name="test", retry_after_ms=100)
         self.assertEqual(err.error_dict(None).get("retry_after_ms"), 100)
         assert err.headers is not None
         self.assertEqual(err.headers.get("Retry-After"), "1")
 
     def test_limit_exceeded_rounding(self) -> None:
-        err = self.LimitExceededErrorHeaders(limiter_name="test", retry_after_ms=3001)
+        err = LimitExceededError(limiter_name="test", retry_after_ms=3001)
         self.assertEqual(err.error_dict(None).get("retry_after_ms"), 3001)
         assert err.headers is not None
         self.assertEqual(err.headers.get("Retry-After"), "4")
diff --git a/tests/rest/client/test_login.py b/tests/rest/client/test_login.py
index 3d3a7b0aa7..3a1f150082 100644
--- a/tests/rest/client/test_login.py
+++ b/tests/rest/client/test_login.py
@@ -177,7 +177,6 @@ class LoginRestServletTestCase(unittest.HomeserverTestCase):
                 # rc_login dict here, we need to set this manually as well
                 "account": {"per_second": 10000, "burst_count": 10000},
             },
-            "experimental_features": {"msc4041_enabled": True},
         }
     )
     def test_POST_ratelimiting_per_address(self) -> None:
@@ -229,7 +228,6 @@ class LoginRestServletTestCase(unittest.HomeserverTestCase):
                 # rc_login dict here, we need to set this manually as well
                 "address": {"per_second": 10000, "burst_count": 10000},
             },
-            "experimental_features": {"msc4041_enabled": True},
         }
     )
     def test_POST_ratelimiting_per_account(self) -> None:
@@ -278,7 +276,6 @@ class LoginRestServletTestCase(unittest.HomeserverTestCase):
                 "address": {"per_second": 10000, "burst_count": 10000},
                 "failed_attempts": {"per_second": 0.17, "burst_count": 5},
             },
-            "experimental_features": {"msc4041_enabled": True},
         }
     )
     def test_POST_ratelimiting_per_account_failed_attempts(self) -> None: