Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Allowed headers on errors to be conditional based on config setting.
Browse files Browse the repository at this point in the history
  • Loading branch information
Half-Shot committed Aug 22, 2023
1 parent b26a203 commit f04efbf
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 18 deletions.
38 changes: 24 additions & 14 deletions synapse/api/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,12 @@ class CodeMessageException(RuntimeError):
Attributes:
code: HTTP error code
msg: string describing the error
headers: optional response headers to send
"""

def __init__(
self,
code: Union[int, HTTPStatus],
msg: str,
headers: Optional[Dict[str, str]] = None,
):
super().__init__("%d: %s" % (code, msg))

Expand All @@ -146,7 +144,11 @@ def __init__(
# To eliminate this behaviour, we convert them to their integer equivalents here.
self.code = int(code)
self.msg = msg
self.headers = headers

def headers_dict(
self, config: Optional["HomeServerConfig"]
) -> Optional[Dict[str, str]]:
return None


class RedirectException(CodeMessageException):
Expand Down Expand Up @@ -192,7 +194,6 @@ def __init__(
msg: str,
errcode: str = Codes.UNKNOWN,
additional_fields: Optional[Dict] = None,
headers: Optional[Dict[str, str]] = None,
):
"""Constructs a synapse error.
Expand All @@ -201,7 +202,7 @@ def __init__(
msg: The human-readable error message.
errcode: The matrix error code e.g 'M_FORBIDDEN'
"""
super().__init__(code, msg, headers)
super().__init__(code, msg)
self.errcode = errcode
if additional_fields is None:
self._additional_fields: Dict = {}
Expand Down Expand Up @@ -360,11 +361,14 @@ def __init__(
self,
required_scopes: List[str],
):
headers = {
self.required_scopes = required_scopes
super().__init__(401, "Insufficient scope", Codes.FORBIDDEN, None)

def headers_dict(self, config: Optional["HomeServerConfig"]) -> Dict[str, str]:
return {
"WWW-Authenticate": 'Bearer error="insufficient_scope", scope="%s"'
% (" ".join(required_scopes))
% (" ".join(self.required_scopes))
}
super().__init__(401, "Insufficient scope", Codes.FORBIDDEN, None, headers)


class UnstableSpecAuthError(AuthError):
Expand Down Expand Up @@ -511,17 +515,23 @@ def __init__(
retry_after_ms: Optional[int] = None,
errcode: str = Codes.LIMIT_EXCEEDED,
):
headers = (
None
if retry_after_ms is None
else {"Retry-After": str(math.ceil(retry_after_ms / 1000))}
)
super().__init__(code, msg, errcode, headers=headers)
super().__init__(code, msg, errcode)
self.retry_after_ms = retry_after_ms

def error_dict(self, config: Optional["HomeServerConfig"]) -> "JsonDict":
return cs_error(self.msg, self.errcode, retry_after_ms=self.retry_after_ms)

def headers_dict(
self, config: Optional["HomeServerConfig"]
) -> Optional[Dict[str, str]]:
if (
self.retry_after_ms is not None
and config
and config.experimental.msc4041_enabled
):
return {"Retry-After": str(math.ceil(self.retry_after_ms / 1000))}
return None


class RoomKeysVersionError(SynapseError):
"""A client has tried to upload to a non-current version of the room_keys store"""
Expand Down
3 changes: 3 additions & 0 deletions synapse/config/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,6 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
self.msc4010_push_rules_account_data = experimental.get(
"msc4010_push_rules_account_data", False
)

# MSC4041: Use http header Retry-After to enable library-assisted retry handling
self.msc4041_enabled: bool = experimental.get("msc4041_enabled", False)
10 changes: 6 additions & 4 deletions synapse/http/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ def return_json_error(
exc: SynapseError = f.value
error_code = exc.code
error_dict = exc.error_dict(config)
if exc.headers is not None:
for header, value in exc.headers.items():
headers_dict = exc.headers_dict(config)
if headers_dict is not None:
for header, value in headers_dict.items():
request.setHeader(header, value)
logger.info("%s SynapseError: %s - %s", request, error_code, exc.msg)
elif f.check(CancelledError):
Expand Down Expand Up @@ -176,8 +177,9 @@ def return_html_error(
cme: CodeMessageException = f.value
code = cme.code
msg = cme.msg
if cme.headers is not None:
for header, value in cme.headers.items():
headers = cme.headers_dict(None)
if headers is not None:
for header, value in headers.items():
request.setHeader(header, value)

if isinstance(cme, RedirectException):
Expand Down

0 comments on commit f04efbf

Please sign in to comment.