Skip to content

Commit

Permalink
Fix not being able to add custom endpoints to the appservice's expres…
Browse files Browse the repository at this point in the history
…s instance (#349)

* Add failing test

* Fix endpoint registration ordering
  • Loading branch information
turt2live committed Oct 26, 2023
1 parent 8aebc8e commit cbbd9f8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
14 changes: 8 additions & 6 deletions src/appservice/Appservice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,7 @@ export class Appservice extends EventEmitter {
this.app.post("/_matrix/app/v1/unstable/org.matrix.msc3984/keys/query", this.onKeysQuery.bind(this));
this.app.post("/unstable/org.matrix.msc3984/keys/query", this.onKeysQuery.bind(this));

// Everything else should 404
// Technically, according to https://spec.matrix.org/v1.6/application-service-api/#unknown-routes we should
// be returning 405 for *known* endpoints with the wrong method.
this.app.all("*", (req: express.Request, res: express.Response) => {
res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
});
// We register the 404 handler in the `begin()` function to allow consumers to add their own endpoints.

if (!this.registration.namespaces || !this.registration.namespaces.users || this.registration.namespaces.users.length === 0) {
throw new Error("No user namespaces in registration");
Expand Down Expand Up @@ -381,6 +376,13 @@ export class Appservice extends EventEmitter {
*/
public begin(): Promise<void> {
return new Promise<void>((resolve, reject) => {
// Per constructor, all other endpoints should 404.
// Technically, according to https://spec.matrix.org/v1.6/application-service-api/#unknown-routes we should
// be returning 405 for *known* endpoints with the wrong method.
this.app.all("*", (req: express.Request, res: express.Response) => {
res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
});

this.appServer = this.app.listen(this.options.port, this.options.bindAddress, () => resolve());
}).then(async () => {
if (this.options.intentOptions?.encryption) {
Expand Down
38 changes: 38 additions & 0 deletions test/appservice/AppserviceTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,44 @@ describe('Appservice', () => {
}
});

it('should allow custom endpoints to be added to the express instance', async () => {
const port = await getPort();
const hsToken = "s3cret_token";
const appservice = new Appservice({
port: port,
bindAddress: '',
homeserverName: 'example.org',
homeserverUrl: 'https://localhost',
registration: {
as_token: "",
hs_token: hsToken,
sender_localpart: "_bot_",
namespaces: {
users: [{ exclusive: true, regex: "@_prefix_.*:.+" }],
rooms: [],
aliases: [],
},
},
});
appservice.botIntent.ensureRegistered = () => {
return null;
};

appservice.expressAppInstance.get("/test", (_, res) => res.sendStatus(200));

await appservice.begin();

try {
const res = await requestPromise({
uri: `http://localhost:${port}/test`,
method: "GET",
});
expect(res).toEqual("OK");
} finally {
appservice.stop();
}
});

// TODO: Populate once intent tests are stable

it.skip('should not try decryption if crypto is not possible', async () => {
Expand Down

0 comments on commit cbbd9f8

Please sign in to comment.