Skip to content

Commit

Permalink
fix(server): Support custom Lobby API middleware (#992)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
fladrif committed Aug 27, 2021
1 parent 3a2a89b commit 8b871ab
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 31 deletions.
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"@types/node": "^14.0.24",
"@types/react": "^16.14.11",
"@types/react-dom": "^16.9.14",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^4.28.5",
"@typescript-eslint/parser": "^4.28.5",
"babel-plugin-module-resolver": "^4.1.0",
Expand Down
16 changes: 9 additions & 7 deletions src/server/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

import request from 'supertest';
import Koa from 'koa';
import Router from 'koa-router';
import * as dateMock from 'jest-date-mock';

import { createRouter, configureApp } from './api';
import { configureRouter, configureApp } from './api';
import { ProcessGameConfig } from '../core/game';
import { Auth } from './auth';
import * as StorageAPI from './db/base';
Expand Down Expand Up @@ -70,16 +71,17 @@ class AsyncStorage extends StorageAPI.Async {
}
}

describe('.createRouter', () => {
describe('.configureRouter', () => {
function addApiToServer({
app,
origins,
...args
}: {
app: Server.App;
origins?: Parameters<typeof configureApp>[2];
} & Parameters<typeof createRouter>[0]) {
const router = createRouter(args);
} & Omit<Parameters<typeof configureRouter>[0], 'router'>) {
const router = new Router<any, Server.AppCtx>();
configureRouter({ router, ...args });
configureApp(app, router, origins);
}

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

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

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

test('disallows non-matching origin', async () => {
const { res } = await request(app.callback())
const res = await request(app.callback())
.get('/games')
.set('Origin', 'https://www.other.com')
.expect('Vary', 'Origin');
Expand Down
10 changes: 5 additions & 5 deletions src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import type Koa from 'koa';
import Router from 'koa-router';
import type Router from 'koa-router';
import koaBody from 'koa-body';
import { nanoid } from 'nanoid';
import cors from '@koa/cors';
Expand Down Expand Up @@ -70,19 +70,19 @@ const createClientMatchData = (
};
};

export const createRouter = ({
export const configureRouter = ({
router,
db,
auth,
games,
uuid = () => nanoid(11),
}: {
router: Router<any, Server.AppCtx>;
auth: Auth;
games: Game[];
uuid?: () => string;
db: StorageAPI.Sync | StorageAPI.Async;
}): Router<any, Server.AppCtx> => {
const router = new Router<any, Server.AppCtx>();

}) => {
/**
* List available games.
*
Expand Down
36 changes: 19 additions & 17 deletions src/server/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* https://opensource.org/licenses/MIT.
*/

import request from 'supertest';

import { Server, createServerRunConfig, getPortFromServer } from '.';
import type { KoaServer } from '.';
import type { SocketIO } from './transport/socketio';
Expand Down Expand Up @@ -46,23 +48,6 @@ jest.mock('koa-socket-2', () => {
};
});

jest.mock('koa', () => {
return class {
constructor() {
(this as any).context = {};
(this as any).use = () => this;
(this as any).callback = () => {};
(this as any).listen = (port, listeningCallback?: () => void) => {
if (listeningCallback) listeningCallback();
return {
address: () => ({ port: 'mock-api-port' }),
close: () => {},
};
};
}
};
});

describe('new', () => {
test('custom db implementation', () => {
const game = {};
Expand Down Expand Up @@ -150,6 +135,23 @@ describe('run', () => {
});
expect(apiCallback).toHaveBeenCalled();
});

test('runs route middleware', async () => {
const usedMiddleware = jest.fn(async (_ctx, next) => {
await next;
});
const unusedMiddleware = jest.fn(async (_ctx, next) => {
await next;
});
server = Server({ games: [game] });
server.router.use('/games', usedMiddleware);
server.router.use('/games/unused', unusedMiddleware);
runningServer = await server.run(8888);

await request(runningServer.appServer).get('/games');
expect(usedMiddleware).toHaveBeenCalled();
expect(unusedMiddleware).not.toHaveBeenCalled();
});
});

describe('kill', () => {
Expand Down
6 changes: 4 additions & 2 deletions src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
*/

import Koa from 'koa';
import Router from 'koa-router';
import type IOTypes from 'socket.io';

import { createRouter, configureApp } from './api';
import { configureRouter, configureApp } from './api';
import { DBFromEnv } from './db';
import { ProcessGameConfig } from '../core/game';
import * as logger from '../core/logger';
Expand Down Expand Up @@ -117,7 +118,7 @@ export function Server({
}
transport.init(app, games, origins);

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

return {
app,
Expand All @@ -128,6 +129,7 @@ export function Server({

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

// DB
await db.connect();
Expand Down

0 comments on commit 8b871ab

Please sign in to comment.