Skip to content

Commit 8b871ab

Browse files
authored
fix(server): Support custom Lobby API middleware (#992)
* feat: Move game server route creation to run Allow user defined middleware to execute on boardgame.io defined routes. Previously created routes were instantiated before user could define middleware and thus they would not execute. * test: Add user defined router middleware tests
1 parent 3a2a89b commit 8b871ab

6 files changed

Lines changed: 63 additions & 31 deletions

File tree

package-lock.json

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"@types/node": "^14.0.24",
9797
"@types/react": "^16.14.11",
9898
"@types/react-dom": "^16.9.14",
99+
"@types/supertest": "^2.0.11",
99100
"@typescript-eslint/eslint-plugin": "^4.28.5",
100101
"@typescript-eslint/parser": "^4.28.5",
101102
"babel-plugin-module-resolver": "^4.1.0",

src/server/api.test.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88

99
import request from 'supertest';
1010
import Koa from 'koa';
11+
import Router from 'koa-router';
1112
import * as dateMock from 'jest-date-mock';
1213

13-
import { createRouter, configureApp } from './api';
14+
import { configureRouter, configureApp } from './api';
1415
import { ProcessGameConfig } from '../core/game';
1516
import { Auth } from './auth';
1617
import * as StorageAPI from './db/base';
@@ -70,16 +71,17 @@ class AsyncStorage extends StorageAPI.Async {
7071
}
7172
}
7273

73-
describe('.createRouter', () => {
74+
describe('.configureRouter', () => {
7475
function addApiToServer({
7576
app,
7677
origins,
7778
...args
7879
}: {
7980
app: Server.App;
8081
origins?: Parameters<typeof configureApp>[2];
81-
} & Parameters<typeof createRouter>[0]) {
82-
const router = createRouter(args);
82+
} & Omit<Parameters<typeof configureRouter>[0], 'router'>) {
83+
const router = new Router<any, Server.AppCtx>();
84+
configureRouter({ router, ...args });
8385
configureApp(app, router, origins);
8486
}
8587

@@ -1528,7 +1530,7 @@ describe('.createRouter', () => {
15281530
const app = createApiServer({ auth, games, db, origins: false });
15291531

15301532
test('does not allow CORS', async () => {
1531-
const { res } = await request(app.callback())
1533+
const res = await request(app.callback())
15321534
.get('/games')
15331535
.set('Origin', 'https://www.example.com')
15341536
.expect('Vary', 'Origin');
@@ -1542,7 +1544,7 @@ describe('.createRouter', () => {
15421544
const app = createApiServer({ auth, games, db, origins: origin });
15431545

15441546
test('disallows non-matching origin', async () => {
1545-
const { res } = await request(app.callback())
1547+
const res = await request(app.callback())
15461548
.get('/games')
15471549
.set('Origin', 'https://www.other.com')
15481550
.expect('Vary', 'Origin');
@@ -1565,7 +1567,7 @@ describe('.createRouter', () => {
15651567
const app = createApiServer({ auth, games, db, origins });
15661568

15671569
test('disallows non-matching origin', async () => {
1568-
const { res } = await request(app.callback())
1570+
const res = await request(app.callback())
15691571
.get('/games')
15701572
.set('Origin', 'https://www.other.com')
15711573
.expect('Vary', 'Origin');

src/server/api.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import type Koa from 'koa';
10-
import Router from 'koa-router';
10+
import type Router from 'koa-router';
1111
import koaBody from 'koa-body';
1212
import { nanoid } from 'nanoid';
1313
import cors from '@koa/cors';
@@ -70,19 +70,19 @@ const createClientMatchData = (
7070
};
7171
};
7272

73-
export const createRouter = ({
73+
export const configureRouter = ({
74+
router,
7475
db,
7576
auth,
7677
games,
7778
uuid = () => nanoid(11),
7879
}: {
80+
router: Router<any, Server.AppCtx>;
7981
auth: Auth;
8082
games: Game[];
8183
uuid?: () => string;
8284
db: StorageAPI.Sync | StorageAPI.Async;
83-
}): Router<any, Server.AppCtx> => {
84-
const router = new Router<any, Server.AppCtx>();
85-
85+
}) => {
8686
/**
8787
* List available games.
8888
*

src/server/index.test.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* https://opensource.org/licenses/MIT.
77
*/
88

9+
import request from 'supertest';
10+
911
import { Server, createServerRunConfig, getPortFromServer } from '.';
1012
import type { KoaServer } from '.';
1113
import type { SocketIO } from './transport/socketio';
@@ -46,23 +48,6 @@ jest.mock('koa-socket-2', () => {
4648
};
4749
});
4850

49-
jest.mock('koa', () => {
50-
return class {
51-
constructor() {
52-
(this as any).context = {};
53-
(this as any).use = () => this;
54-
(this as any).callback = () => {};
55-
(this as any).listen = (port, listeningCallback?: () => void) => {
56-
if (listeningCallback) listeningCallback();
57-
return {
58-
address: () => ({ port: 'mock-api-port' }),
59-
close: () => {},
60-
};
61-
};
62-
}
63-
};
64-
});
65-
6651
describe('new', () => {
6752
test('custom db implementation', () => {
6853
const game = {};
@@ -150,6 +135,23 @@ describe('run', () => {
150135
});
151136
expect(apiCallback).toHaveBeenCalled();
152137
});
138+
139+
test('runs route middleware', async () => {
140+
const usedMiddleware = jest.fn(async (_ctx, next) => {
141+
await next;
142+
});
143+
const unusedMiddleware = jest.fn(async (_ctx, next) => {
144+
await next;
145+
});
146+
server = Server({ games: [game] });
147+
server.router.use('/games', usedMiddleware);
148+
server.router.use('/games/unused', unusedMiddleware);
149+
runningServer = await server.run(8888);
150+
151+
await request(runningServer.appServer).get('/games');
152+
expect(usedMiddleware).toHaveBeenCalled();
153+
expect(unusedMiddleware).not.toHaveBeenCalled();
154+
});
153155
});
154156

155157
describe('kill', () => {

src/server/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
*/
88

99
import Koa from 'koa';
10+
import Router from 'koa-router';
1011
import type IOTypes from 'socket.io';
1112

12-
import { createRouter, configureApp } from './api';
13+
import { configureRouter, configureApp } from './api';
1314
import { DBFromEnv } from './db';
1415
import { ProcessGameConfig } from '../core/game';
1516
import * as logger from '../core/logger';
@@ -117,7 +118,7 @@ export function Server({
117118
}
118119
transport.init(app, games, origins);
119120

120-
const router = createRouter({ db, games, uuid, auth });
121+
const router = new Router<any, ServerTypes.AppCtx>();
121122

122123
return {
123124
app,
@@ -128,6 +129,7 @@ export function Server({
128129

129130
run: async (portOrConfig: number | ServerConfig, callback?: () => void) => {
130131
const serverRunConfig = createServerRunConfig(portOrConfig, callback);
132+
configureRouter({ router, db, games, uuid, auth });
131133

132134
// DB
133135
await db.connect();

0 commit comments

Comments
 (0)