Compare commits
2 Commits
devon/pin-
...
anoa/modul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ac38a1109 | ||
|
|
29cc17fde7 |
1
changelog.d/15149.feature
Normal file
1
changelog.d/15149.feature
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Add a new `send_federation_http_request` method to the Module API to allow Synapse modules to make matrix federation requests over HTTP.
|
||||||
@@ -37,7 +37,12 @@ from twisted.internet import defer
|
|||||||
from twisted.web.resource import Resource
|
from twisted.web.resource import Resource
|
||||||
|
|
||||||
from synapse.api import errors
|
from synapse.api import errors
|
||||||
from synapse.api.errors import SynapseError
|
from synapse.api.errors import (
|
||||||
|
FederationDeniedError,
|
||||||
|
HttpResponseException,
|
||||||
|
RequestSendFailed,
|
||||||
|
SynapseError,
|
||||||
|
)
|
||||||
from synapse.events import EventBase
|
from synapse.events import EventBase
|
||||||
from synapse.events.presence_router import (
|
from synapse.events.presence_router import (
|
||||||
GET_INTERESTED_USERS_CALLBACK,
|
GET_INTERESTED_USERS_CALLBACK,
|
||||||
@@ -129,6 +134,14 @@ from synapse.util import Clock
|
|||||||
from synapse.util.async_helpers import maybe_awaitable
|
from synapse.util.async_helpers import maybe_awaitable
|
||||||
from synapse.util.caches.descriptors import CachedFunction, cached as _cached
|
from synapse.util.caches.descriptors import CachedFunction, cached as _cached
|
||||||
from synapse.util.frozenutils import freeze
|
from synapse.util.frozenutils import freeze
|
||||||
|
from synapse.util.retryutils import NotRetryingDestination
|
||||||
|
|
||||||
|
from .errors import (
|
||||||
|
FederationHttpDeniedException,
|
||||||
|
FederationHttpNotRetryingDestinationException,
|
||||||
|
FederationHttpRequestSendFailedException,
|
||||||
|
FederationHttpResponseException,
|
||||||
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from synapse.app.generic_worker import GenericWorkerSlavedStore
|
from synapse.app.generic_worker import GenericWorkerSlavedStore
|
||||||
@@ -1612,6 +1625,123 @@ class ModuleApi:
|
|||||||
deactivation=deactivation,
|
deactivation=deactivation,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _try_federation_http_request(
|
||||||
|
self,
|
||||||
|
method: str,
|
||||||
|
remote_server_name: str,
|
||||||
|
path: str,
|
||||||
|
query_parameters: Optional[Dict[str, Any]],
|
||||||
|
body: Optional[JsonDict] = None,
|
||||||
|
timeout: Optional[int] = None,
|
||||||
|
) -> Union[JsonDict, List]:
|
||||||
|
"""
|
||||||
|
Send a federation request to a remote homeserver and return the response.
|
||||||
|
|
||||||
|
This method assumes the `method` argument is fully capitalised.
|
||||||
|
|
||||||
|
A helper method for self.send_federation_http_request, see that method for
|
||||||
|
more details.
|
||||||
|
"""
|
||||||
|
assert method in ["GET", "PUT", "POST", "DELETE"]
|
||||||
|
|
||||||
|
fed_client = self._hs.get_federation_http_client()
|
||||||
|
|
||||||
|
if method == "GET":
|
||||||
|
return await fed_client.get_json(
|
||||||
|
destination=remote_server_name,
|
||||||
|
path=path,
|
||||||
|
args=query_parameters,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
elif method == "PUT":
|
||||||
|
return await fed_client.put_json(
|
||||||
|
destination=remote_server_name,
|
||||||
|
path=path,
|
||||||
|
args=query_parameters,
|
||||||
|
data=body,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
elif method == "POST":
|
||||||
|
return await fed_client.post_json(
|
||||||
|
destination=remote_server_name,
|
||||||
|
path=path,
|
||||||
|
args=query_parameters,
|
||||||
|
data=body,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
elif method == "DELETE":
|
||||||
|
return await fed_client.delete_json(
|
||||||
|
destination=remote_server_name,
|
||||||
|
path=path,
|
||||||
|
args=query_parameters,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
async def send_federation_http_request(
|
||||||
|
self,
|
||||||
|
method: str,
|
||||||
|
remote_server_name: str,
|
||||||
|
path: str,
|
||||||
|
query_parameters: Optional[Dict[str, Any]],
|
||||||
|
body: Optional[JsonDict] = None,
|
||||||
|
timeout: Optional[int] = None,
|
||||||
|
) -> Union[JsonDict, List]:
|
||||||
|
"""
|
||||||
|
Send an HTTP federation request to a remote homeserver.
|
||||||
|
|
||||||
|
Added in Synapse v1.79.0.
|
||||||
|
|
||||||
|
If the request is successful, the parsed response body will be returned. If
|
||||||
|
unsuccessful, an exception will be raised. Callers are expected to handle the
|
||||||
|
possible exception cases. See exception class docstrings for a more detailed
|
||||||
|
explanation of each.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
method: The HTTP method to use. Must be one of: "GET", "PUT", "POST",
|
||||||
|
"DELETE".
|
||||||
|
remote_server_name: The remote server to send the request to. This method
|
||||||
|
will resolve delegated homeserver URLs automatically (well-known etc).
|
||||||
|
path: The HTTP path for the request.
|
||||||
|
query_parameters: Any query parameters for the request.
|
||||||
|
body: The body of the request.
|
||||||
|
timeout: The timeout in seconds to wait before giving up on a request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The response to the request as a Python object.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FederationHttpResponseException: If we get an HTTP response code >= 300
|
||||||
|
(except 429).
|
||||||
|
FederationHttpNotRetryingDestinationException: If the homeserver believes the
|
||||||
|
remote homeserver is down and is not yet ready to attempt to contact it.
|
||||||
|
FederationHttpDeniedException: If this destination is not on the local
|
||||||
|
homeserver's configured federation whitelist.
|
||||||
|
FederationHttpRequestSendFailedException: If there were problems connecting
|
||||||
|
to the remote, due to e.g. DNS failures, connection timeouts etc.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return await self._try_federation_http_request(
|
||||||
|
method.upper(), remote_server_name, path, query_parameters, body, timeout
|
||||||
|
)
|
||||||
|
except HttpResponseException as e:
|
||||||
|
raise FederationHttpResponseException(
|
||||||
|
remote_server_name,
|
||||||
|
status_code=e.code,
|
||||||
|
msg=e.msg,
|
||||||
|
response_body=e.response,
|
||||||
|
)
|
||||||
|
except NotRetryingDestination:
|
||||||
|
raise FederationHttpNotRetryingDestinationException(remote_server_name)
|
||||||
|
except FederationDeniedError:
|
||||||
|
raise FederationHttpDeniedException(remote_server_name)
|
||||||
|
except RequestSendFailed as e:
|
||||||
|
raise FederationHttpRequestSendFailedException(
|
||||||
|
remote_server_name,
|
||||||
|
can_retry=e.can_retry,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PublicRoomListManager:
|
class PublicRoomListManager:
|
||||||
"""Contains methods for adding to, removing from and querying whether a room
|
"""Contains methods for adding to, removing from and querying whether a room
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Exception types which are exposed as part of the stable module API"""
|
"""Exception types which are exposed as part of the stable module API"""
|
||||||
|
import attr
|
||||||
|
|
||||||
from synapse.api.errors import (
|
from synapse.api.errors import (
|
||||||
Codes,
|
Codes,
|
||||||
@@ -24,6 +25,57 @@ from synapse.config._base import ConfigError
|
|||||||
from synapse.handlers.push_rules import InvalidRuleException
|
from synapse.handlers.push_rules import InvalidRuleException
|
||||||
from synapse.storage.push_rule import RuleNotFoundException
|
from synapse.storage.push_rule import RuleNotFoundException
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(auto_attribs=True)
|
||||||
|
class FederationHttpResponseException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when an HTTP request over federation returns a status code > 300 (and not 429).
|
||||||
|
"""
|
||||||
|
|
||||||
|
remote_server_name: str
|
||||||
|
# The HTTP status code of the response.
|
||||||
|
status_code: int
|
||||||
|
# A human-readable explanation for the error.
|
||||||
|
msg: str
|
||||||
|
# The non-parsed HTTP response body.
|
||||||
|
response_body: bytes
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(auto_attribs=True)
|
||||||
|
class FederationHttpNotRetryingDestinationException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when the local homeserver refuses to send traffic to a remote homeserver that
|
||||||
|
it believes is experiencing an outage.
|
||||||
|
"""
|
||||||
|
|
||||||
|
remote_server_name: str
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(auto_attribs=True)
|
||||||
|
class FederationHttpDeniedException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when the local homeserver refuses to send federation traffic to a remote
|
||||||
|
homeserver. This is due to the remote homeserver not being on the configured
|
||||||
|
federation whitelist.
|
||||||
|
"""
|
||||||
|
|
||||||
|
remote_server_name: str
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(auto_attribs=True)
|
||||||
|
class FederationHttpRequestSendFailedException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when there are problems connecting to the remote homeserver due to e.g.
|
||||||
|
DNS failures, connection timeouts, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
remote_server_name: str
|
||||||
|
# Whether the request can be retried with a chance of success. This will be True
|
||||||
|
# if the failure occurred due to e.g. timeouts, a disruption in the connection etc.
|
||||||
|
# Will be false in the case of e.g. a malformed response from the remote homeserver.
|
||||||
|
can_retry: bool
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Codes",
|
"Codes",
|
||||||
"InvalidClientCredentialsError",
|
"InvalidClientCredentialsError",
|
||||||
@@ -32,4 +84,8 @@ __all__ = [
|
|||||||
"ConfigError",
|
"ConfigError",
|
||||||
"InvalidRuleException",
|
"InvalidRuleException",
|
||||||
"RuleNotFoundException",
|
"RuleNotFoundException",
|
||||||
|
"FederationHttpResponseException",
|
||||||
|
"FederationHttpNotRetryingDestinationException",
|
||||||
|
"FederationHttpDeniedException",
|
||||||
|
"FederationHttpRequestSendFailedException",
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user