Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC2659: Application service ping endpoint #2659

Merged
merged 18 commits into from
May 9, 2023
Merged
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions proposals/2659-appservice-ping.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Application service ping endpoint
# MSC2659: Application service ping endpoint

## Problem
A relatively common problem when setting up appservices is the connection
Expand All @@ -22,16 +22,24 @@ This endpoint is on the appservice side. Like all other appservice-side
endpoints, it is authenticated using the `hs_token`. When the token is correct,
this returns HTTP 200 and an empty JSON object as the body.

The request body contains an optional `transaction_id` string field, which
comes from the client ping request defined below.

Appservices don't need to have any special behavior on this endpoint, but they
may use the incoming request to verify that an outgoing ping actually pinged
the appservice rather than going somewhere else.
tulir marked this conversation as resolved.
Show resolved Hide resolved

This proposal doesn't define any cases where a homeserver would call the ping
endpoint unless explicitly requested by the appservice (using the client
endpoint below). Therefore, appservices don't necessarily have to implement
this endpoint if they never call the client ping endpoint.

### `POST /_matrix/client/v1/appservice/{appserviceId}/ping`
When the endpoint is called, the homeserver makes a `/_matrix/app/v1/ping`
request to the appservice.

The request body may contain a `transaction_id` field, which, if present, must
be passed through to the appservice `/ping` request body as-is.
The request body may contain a `transaction_id` string field, which, if present,
must be passed through to the appservice `/ping` request body as-is.

This endpoint is only allowed when using a valid appservice token, and it can
only ping the appservice associated with the token. If the token or appservice
Expand All @@ -45,8 +53,8 @@ should be retried.

#### Response
If the ping request returned successfully, the endpoint returns HTTP 200. The
response body has a `duration` field containing the ping request roundtrip time
as milliseconds.
response body has a `duration` field containing the `/_matrix/app/v1/ping`
tulir marked this conversation as resolved.
Show resolved Hide resolved
request roundtrip time as milliseconds.

If the request fails, the endpoint returns a standard error response with
`errcode`s and HTTP status codes as specified below:
Expand All @@ -59,11 +67,28 @@ If the request fails, the endpoint returns a standard error response with
* For other connection errors, `M_CONNECTION_FAILED` and HTTP 502.
It is recommended to put a more detailed explanation in the `error` field.

### Example flow

1. bridge -> homeserver (request #1): `POST http://synapse:8008/_matrix/client/v1/appservice/whatsapp/ping`
* Header `Authorization: Bearer as_token`
* Body: `{"transaction_id": "meow"}`
2. homeserver -> bridge (request #2): `POST http://bridge:29318/_matrix/app/v1/ping`
* Header `Authorization: Bearer hs_token`
* Body: `{"transaction_id": "meow"}`
3. bridge -> homeserver (response to #2): 200 OK with body `{}`
4. homeserver -> bridge (response to #1): 200 OK with body `{"duration": 123}`
(123 milliseconds being the time it took for request #2 to complete).

## Alternatives
turt2live marked this conversation as resolved.
Show resolved Hide resolved

* The ping could make an empty `/transactions` request instead of adding a new
ping endpoint. A new endpoint was found to be cleaner while implementing, and
there didn't seem to be any significant benefits to reusing transactions.
* A `/versions` endpoint could be introduced to work for both pinging and
checking what spec versions an appservice supports. However, it's not clear
that a new endpoint is the best way to detect version support (a simple flag
in the registration file may be preferable), so this MSC proposes a `/ping`
endpoint that doesn't have other behavior.
* Appservices could be switched to using websockets instead of the server
pushing events. This option is already used by some bridges, but implementing
websocket support on the homeserver side is much more complicated than a
Expand Down