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

Synapse accepts a PUT /createRoom request #14535

Open
DMRobertson opened this issue Nov 23, 2022 · 6 comments
Open

Synapse accepts a PUT /createRoom request #14535

DMRobertson opened this issue Nov 23, 2022 · 6 comments
Labels
A-Spec-Compliance places where synapse does not conform to the spec O-Uncommon Most users are unlikely to come across this or unexpected workflow S-Tolerable Minor significance, cosmetic issues, low or no impact to users. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. Z-Cleanup Things we want to get rid of, but aren't actively causing pain

Comments

@DMRobertson
Copy link
Contributor

But the spec says it's only to be POSTed.

https://spec.matrix.org/v1.5/client-server-api/#creation

In particular, /createRoom is not idempotent, so it shouldn't be a PUT.

@DMRobertson DMRobertson added A-Spec-Compliance places where synapse does not conform to the spec S-Tolerable Minor significance, cosmetic issues, low or no impact to users. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. O-Uncommon Most users are unlikely to come across this or unexpected workflow X-Consult-Clients Need to investigate if this change breaks clients Z-Cleanup Things we want to get rid of, but aren't actively causing pain labels Nov 23, 2022
@DMRobertson
Copy link
Contributor Author

matrix-org/matrix-spec#222 confuses the matter somewhat

@DMRobertson
Copy link
Contributor Author

Pinged clients here'; no requests to PUT /_matrix/client/[^/]*/createRoom HTTP in the last day. Let's bin it.

@DMRobertson DMRobertson added good first issue Good for newcomers and removed X-Consult-Clients Need to investigate if this change breaks clients good first issue Good for newcomers labels Nov 23, 2022
@DMRobertson
Copy link
Contributor Author

Hmm. On reflection it looks like the implementation is handling a transaction id:

def on_PUT(
self, request: SynapseRequest, txn_id: str
) -> Awaitable[Tuple[int, JsonDict]]:
set_tag("txn_id", txn_id)
return self.txns.fetch_or_execute_request(request, self.on_POST, request)

which means it's doing exactly what matrix-org/matrix-spec#222 asks for. Maybe we just add this to the spec?

@tulir
Copy link
Member

tulir commented Nov 30, 2022

How is it handling a transaction ID without a transaction ID parameter in the path? Also, is it actually idempotent or does it just eat a transaction ID and do nothing with it?

I'd say it's safe to remove either way and re-add properly once there's a MSC.

@DMRobertson
Copy link
Contributor Author

DMRobertson commented Nov 30, 2022

How is it handling a transaction ID without a transaction ID parameter in the path?

See

def register(self, http_server: HttpServer) -> None:
PATTERNS = "/createRoom"
register_txn_path(self, PATTERNS, http_server)

and the implementation of register_txn_path.

Also, is it actually idempotent or does it just eat a transaction ID and do nothing with it?

It looks idempotent enough to me. The transaction id is included here in the key we use to deduplicate requests:

def fetch_or_execute_request(
self,
request: Request,
fn: Callable[P, Awaitable[Tuple[int, JsonDict]]],
*args: P.args,
**kwargs: P.kwargs,
) -> Awaitable[Tuple[int, JsonDict]]:
"""A helper function for fetch_or_execute which extracts
a transaction key from the given request.
See:
fetch_or_execute
"""
return self.fetch_or_execute(
self._get_transaction_key(request), fn, *args, **kwargs
)

def _get_transaction_key(self, request: Request) -> str:
"""A helper function which returns a transaction key that can be used
with TransactionCache for idempotent requests.
Idempotency is based on the returned key being the same for separate
requests to the same endpoint. The key is formed from the HTTP request
path and the access_token for the requesting user.
Args:
request: The incoming request. Must contain an access_token.
Returns:
A transaction key
"""
assert request.path is not None
token = self.auth.get_access_token_from_request(request)
return request.path.decode("utf8") + "/" + token

A comment suggests that we guarantee deduplication within a 30 minute range.

self.transactions: Dict[
str, Tuple[ObservableDeferred[Tuple[int, JsonDict]], int]
] = {}
# Try to clean entries every 30 mins. This means entries will exist
# for at *LEAST* 30 mins, and at *MOST* 60 mins.

@tulir
Copy link
Member

tulir commented Nov 30, 2022

Huh, so synapse also has undocumented PUT versions of all the membership and join endpoints 🤔

I guess that just needs a MSC for PUT /createRoom then, although it'd be nice to switch to /create_room too

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A-Spec-Compliance places where synapse does not conform to the spec O-Uncommon Most users are unlikely to come across this or unexpected workflow S-Tolerable Minor significance, cosmetic issues, low or no impact to users. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. Z-Cleanup Things we want to get rid of, but aren't actively causing pain
Projects
None yet
Development

No branches or pull requests

2 participants