Skip to content

Commit

Permalink
Reply with 503 to unknown API requests at the preboot stage. (#116593)
Browse files Browse the repository at this point in the history
  • Loading branch information
azasypkin committed Nov 2, 2021
1 parent 2d1a088 commit 01ff431
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 4 deletions.
40 changes: 40 additions & 0 deletions src/core/server/core_app/core_app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,46 @@ describe('CoreApp', () => {

expect(mockResponseFactory.renderCoreApp).toHaveBeenCalled();
});

it('main route handles unknown public API requests', () => {
coreApp.preboot(internalCorePreboot, prebootUIPlugins);

const [[, handler]] = prebootHTTPResourcesRegistrar.register.mock.calls;
const mockResponseFactory = httpResourcesMock.createResponseFactory();
handler(
{} as unknown as RequestHandlerContext,
httpServerMock.createKibanaRequest({ path: '/api/status' }),
mockResponseFactory
);

expect(mockResponseFactory.renderCoreApp).not.toHaveBeenCalled();
expect(mockResponseFactory.customError).toHaveBeenCalledWith({
statusCode: 503,
headers: { 'Retry-After': '30' },
body: 'Kibana server is not ready yet',
bypassErrorFormat: true,
});
});

it('main route handles unknown internal API requests', () => {
coreApp.preboot(internalCorePreboot, prebootUIPlugins);

const [[, handler]] = prebootHTTPResourcesRegistrar.register.mock.calls;
const mockResponseFactory = httpResourcesMock.createResponseFactory();
handler(
{} as unknown as RequestHandlerContext,
httpServerMock.createKibanaRequest({ path: '/internal/security/me' }),
mockResponseFactory
);

expect(mockResponseFactory.renderCoreApp).not.toHaveBeenCalled();
expect(mockResponseFactory.customError).toHaveBeenCalledWith({
statusCode: 503,
headers: { 'Retry-After': '30' },
body: 'Kibana server is not ready yet',
bypassErrorFormat: true,
});
});
});

describe('`/app/{id}/{any*}` route', () => {
Expand Down
22 changes: 18 additions & 4 deletions src/core/server/core_app/core_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Env } from '@kbn/config';
import { schema } from '@kbn/config-schema';
import { fromRoot } from '@kbn/utils';

import { IRouter, IBasePath, IKibanaResponse, KibanaResponseFactory } from '../http';
import { IRouter, IBasePath, IKibanaResponse, KibanaResponseFactory, KibanaRequest } from '../http';
import { HttpResources, HttpResourcesServiceToolkit } from '../http_resources';
import { InternalCorePreboot, InternalCoreSetup } from '../internal_types';
import { CoreContext } from '../core_context';
Expand All @@ -27,6 +27,7 @@ interface CommonRoutesParams {
basePath: IBasePath;
uiPlugins: UiPlugins;
onResourceNotFound: (
req: KibanaRequest,
res: HttpResourcesServiceToolkit & KibanaResponseFactory
) => Promise<IKibanaResponse>;
}
Expand Down Expand Up @@ -64,7 +65,20 @@ export class CoreApp {
httpResources: corePreboot.httpResources.createRegistrar(router),
router,
uiPlugins,
onResourceNotFound: (res) => res.renderCoreApp(),
onResourceNotFound: async (req, res) =>
// THe API consumers might call various Kibana APIs (e.g. `/api/status`) when Kibana is still at the preboot
// stage, and the main HTTP server that registers API handlers isn't up yet. At this stage we don't know if
// the API endpoint exists or not, and hence cannot reply with `404`. We also should not reply with completely
// unexpected response (`200 text/html` for the Core app). The only suitable option is to reply with `503`
// like we do for all other unknown non-GET requests at the preboot stage.
req.route.path.startsWith('/api/') || req.route.path.startsWith('/internal/')
? res.customError({
statusCode: 503,
headers: { 'Retry-After': '30' },
body: 'Kibana server is not ready yet',
bypassErrorFormat: true,
})
: res.renderCoreApp(),
});
});
}
Expand All @@ -91,7 +105,7 @@ export class CoreApp {
httpResources: resources,
router,
uiPlugins,
onResourceNotFound: async (res) => res.notFound(),
onResourceNotFound: async (req, res) => res.notFound(),
});

resources.register(
Expand Down Expand Up @@ -148,7 +162,7 @@ export class CoreApp {
const { query, params } = req;
const { path } = params;
if (!path || !path.endsWith('/') || path.startsWith('/')) {
return onResourceNotFound(res);
return onResourceNotFound(req, res);
}

// remove trailing slash
Expand Down

0 comments on commit 01ff431

Please sign in to comment.