Avoid race condition between HttpServer.stop() and HttpServerSetup methods (#64487)

This commit is contained in:
Josh Dover 2020-04-30 10:32:26 -06:00 committed by GitHub
parent 671d750c03
commit 9112b6c1f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 1 deletions

View file

@ -1068,6 +1068,14 @@ describe('setup contract', () => {
await create();
expect(create()).rejects.toThrowError('A cookieSessionStorageFactory was already created');
});
it('does not throw if called after stop', async () => {
const { createCookieSessionStorageFactory } = await server.setup(config);
await server.stop();
expect(() => {
createCookieSessionStorageFactory(cookieOptions);
}).not.toThrow();
});
});
describe('#isTlsEnabled', () => {
@ -1113,4 +1121,54 @@ describe('setup contract', () => {
expect(getServerInfo().protocol).toEqual('https');
});
});
describe('#registerStaticDir', () => {
it('does not throw if called after stop', async () => {
const { registerStaticDir } = await server.setup(config);
await server.stop();
expect(() => {
registerStaticDir('/path1/{path*}', '/path/to/resource');
}).not.toThrow();
});
});
describe('#registerOnPreAuth', () => {
test('does not throw if called after stop', async () => {
const { registerOnPreAuth } = await server.setup(config);
await server.stop();
expect(() => {
registerOnPreAuth((req, res) => res.unauthorized());
}).not.toThrow();
});
});
describe('#registerOnPostAuth', () => {
test('does not throw if called after stop', async () => {
const { registerOnPostAuth } = await server.setup(config);
await server.stop();
expect(() => {
registerOnPostAuth((req, res) => res.unauthorized());
}).not.toThrow();
});
});
describe('#registerOnPreResponse', () => {
test('does not throw if called after stop', async () => {
const { registerOnPreResponse } = await server.setup(config);
await server.stop();
expect(() => {
registerOnPreResponse((req, res, t) => t.next());
}).not.toThrow();
});
});
describe('#registerAuth', () => {
test('does not throw if called after stop', async () => {
const { registerAuth } = await server.setup(config);
await server.stop();
expect(() => {
registerAuth((req, res) => res.unauthorized());
}).not.toThrow();
});
});
});

View file

@ -74,6 +74,7 @@ export class HttpServer {
private registeredRouters = new Set<IRouter>();
private authRegistered = false;
private cookieSessionStorageCreated = false;
private stopped = false;
private readonly log: Logger;
private readonly authState: AuthStateStorage;
@ -144,6 +145,10 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Http server is not setup up yet');
}
if (this.stopped) {
this.log.warn(`start called after stop`);
return;
}
this.log.debug('starting http server');
for (const router of this.registeredRouters) {
@ -189,13 +194,13 @@ export class HttpServer {
}
public async stop() {
this.stopped = true;
if (this.server === undefined) {
return;
}
this.log.debug('stopping http server');
await this.server.stop();
this.server = undefined;
}
private getAuthOption(
@ -234,6 +239,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Server is not created yet');
}
if (this.stopped) {
this.log.warn(`setupConditionalCompression called after stop`);
}
const { enabled, referrerWhitelist: list } = config.compression;
if (!enabled) {
@ -261,6 +269,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Server is not created yet');
}
if (this.stopped) {
this.log.warn(`registerOnPostAuth called after stop`);
}
this.server.ext('onPostAuth', adoptToHapiOnPostAuthFormat(fn, this.log));
}
@ -269,6 +280,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Server is not created yet');
}
if (this.stopped) {
this.log.warn(`registerOnPreAuth called after stop`);
}
this.server.ext('onRequest', adoptToHapiOnPreAuthFormat(fn, this.log));
}
@ -277,6 +291,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Server is not created yet');
}
if (this.stopped) {
this.log.warn(`registerOnPreResponse called after stop`);
}
this.server.ext('onPreResponse', adoptToHapiOnPreResponseFormat(fn, this.log));
}
@ -288,6 +305,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Server is not created yet');
}
if (this.stopped) {
this.log.warn(`createCookieSessionStorageFactory called after stop`);
}
if (this.cookieSessionStorageCreated) {
throw new Error('A cookieSessionStorageFactory was already created');
}
@ -305,6 +325,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Server is not created yet');
}
if (this.stopped) {
this.log.warn(`registerAuth called after stop`);
}
if (this.authRegistered) {
throw new Error('Auth interceptor was already registered');
}
@ -348,6 +371,9 @@ export class HttpServer {
if (this.server === undefined) {
throw new Error('Http server is not setup up yet');
}
if (this.stopped) {
this.log.warn(`registerStaticDir called after stop`);
}
this.server.route({
path,