Skip to content

Commit

Permalink
Exit customRoute forEach when route found
Browse files Browse the repository at this point in the history
  • Loading branch information
satcheluniverse committed Mar 28, 2023
1 parent 4fa1d62 commit 52c54b3
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/receivers/HTTPReceiver.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,37 @@ describe('HTTPReceiver', function () {
assert.throws(() => receiver.requestListener(fakeReq, fakeRes), HTTPReceiverDeferredRequestError);
});

it('should call custom route handler only if request matches multiple route paths and method including params', async function () {
const HTTPReceiver = await importHTTPReceiver();
const customRoutes = [{ path: '/test/123', method: ['get', 'POST'], handler: sinon.fake() },
{ path: '/test/:id', method: ['get', 'POST'], handler: sinon.fake.throws('Should not be used.') }];
const matchRegex = match(customRoutes[0].path, { decode: decodeURIComponent });
const receiver = new HTTPReceiver({
clientSecret: 'my-client-secret',
signingSecret: 'secret',
customRoutes,
});

const fakeReq: IncomingMessage = sinon.createStubInstance(IncomingMessage) as IncomingMessage;
const fakeRes: ServerResponse = sinon.createStubInstance(ServerResponse) as unknown as ServerResponse;

fakeReq.url = '/test/123';
const tempMatch = matchRegex(fakeReq.url);
if (!tempMatch) throw new Error('match failed');
const params : ParamsDictionary = tempMatch.params as ParamsDictionary;

fakeReq.method = 'GET';
receiver.requestListener(fakeReq, fakeRes);
assert(customRoutes[0].handler.calledWith({ ...fakeReq, params }, fakeRes));

fakeReq.method = 'POST';
receiver.requestListener(fakeReq, fakeRes);
assert(customRoutes[0].handler.calledWith({ ...fakeReq, params }, fakeRes));

fakeReq.method = 'UNHANDLED_METHOD';
assert.throws(() => receiver.requestListener(fakeReq, fakeRes), HTTPReceiverDeferredRequestError);
});

it("should throw an error if customRoutes don't have the required keys", async function () {
const HTTPReceiver = await importHTTPReceiver();
const customRoutes = [{ path: '/test' }] as any;
Expand Down
1 change: 1 addition & 0 deletions src/receivers/HTTPReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export default class HTTPReceiver implements Receiver {
let pathMatch : string | boolean = false;
let params : ParamsDictionary = {};
Object.keys(this.routes).forEach((route) => {
if (pathMatch) return;
const matchRegex = match(route, { decode: decodeURIComponent });
const tempMatch = matchRegex(path);
if (tempMatch) {
Expand Down
1 change: 0 additions & 1 deletion src/receivers/ParamsIncomingMessage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { IncomingMessage } from 'http';
import { ParamsDictionary } from 'express-serve-static-core';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface ParamsIncomingMessage extends IncomingMessage {
/**
* **Only valid for requests with path parameters.**
Expand Down
42 changes: 42 additions & 0 deletions src/receivers/SocketModeReceiver.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,48 @@ describe('SocketModeReceiver', function () {
assert(fakeRes.end.called);
});

it('should call custom route handler only if request matches multiple route paths and method including params', async function () {
// Arrange
const installProviderStub = sinon.createStubInstance(InstallProvider);
const overrides = mergeOverrides(
withHttpCreateServer(this.fakeCreateServer),
withHttpsCreateServer(sinon.fake.throws('Should not be used.')),
);
const SocketModeReceiver = await importSocketModeReceiver(overrides);
const customRoutes = [{ path: '/test/123', method: ['get', 'POST'], handler: sinon.fake() },
{ path: '/test/:id', method: ['get', 'POST'], handler: sinon.fake.throws('Should not be used.') }];
const matchRegex = match(customRoutes[0].path, { decode: decodeURIComponent });

const receiver = new SocketModeReceiver({
appToken: 'my-secret',
customRoutes,
});
assert.isNotNull(receiver);
receiver.installer = installProviderStub as unknown as InstallProvider;

const fakeReq: IncomingMessage = sinon.createStubInstance(IncomingMessage) as IncomingMessage;
const fakeRes = { writeHead: sinon.fake(), end: sinon.fake() };

fakeReq.url = '/test/123';
const tempMatch = matchRegex(fakeReq.url);
if (!tempMatch) throw new Error('match failed');
const params : ParamsDictionary = tempMatch.params as ParamsDictionary;
fakeReq.headers = { host: 'localhost' };

fakeReq.method = 'GET';
await this.listener(fakeReq, fakeRes);
assert(customRoutes[0].handler.calledWith({ ...fakeReq, params }, fakeRes));

fakeReq.method = 'POST';
await this.listener(fakeReq, fakeRes);
assert(customRoutes[0].handler.calledWith({ ...fakeReq, params }, fakeRes));

fakeReq.method = 'UNHANDLED_METHOD';
await this.listener(fakeReq, fakeRes);
assert(fakeRes.writeHead.calledWith(404, sinon.match.object));
assert(fakeRes.end.called);
});

it("should throw an error if customRoutes don't have the required keys", async function () {
// Arrange
const overrides = mergeOverrides(
Expand Down
1 change: 1 addition & 0 deletions src/receivers/SocketModeReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export default class SocketModeReceiver implements Receiver {
let pathMatch : string | boolean = false;
let params : ParamsDictionary = {};
Object.keys(this.routes).forEach((route) => {
if (pathMatch) return;
const matchRegex = match(route, { decode: decodeURIComponent });
const tempMatch = matchRegex(path);
if (tempMatch) {
Expand Down

0 comments on commit 52c54b3

Please sign in to comment.