[Reporting] Fix error handling for job handler in route (#60161)

* fix bogus rison error

* add generate route test

* update test name
This commit is contained in:
Tim Sullivan 2020-03-16 14:26:47 -07:00 committed by GitHub
parent 132383c28c
commit 537fa8c1eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 147 additions and 2 deletions

View file

@ -82,16 +82,21 @@ export function registerGenerateFromJobParams(
}
const { exportType } = request.params;
let jobParams;
let response;
try {
const jobParams = rison.decode(jobParamsRison) as object | null;
jobParams = rison.decode(jobParamsRison) as object | null;
if (!jobParams) {
throw new Error('missing jobParams!');
}
response = await handler(exportType, jobParams, legacyRequest, h);
} catch (err) {
throw boom.badRequest(`invalid rison: ${jobParamsRison}`);
}
try {
response = await handler(exportType, jobParams, legacyRequest, h);
} catch (err) {
throw handleError(exportType, err);
}
return response;
},
});

View file

@ -0,0 +1,140 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import Hapi from 'hapi';
import { createMockReportingCore } from '../../test_helpers';
import { Logger, ServerFacade } from '../../types';
import { ReportingCore, ReportingSetupDeps } from '../../server/types';
jest.mock('./lib/authorized_user_pre_routing', () => ({
authorizedUserPreRoutingFactory: () => () => ({}),
}));
jest.mock('./lib/reporting_feature_pre_routing', () => ({
reportingFeaturePreRoutingFactory: () => () => () => ({
jobTypes: ['unencodedJobType', 'base64EncodedJobType'],
}),
}));
import { registerJobGenerationRoutes } from './generation';
let mockServer: Hapi.Server;
let mockReportingPlugin: ReportingCore;
const mockLogger = ({
error: jest.fn(),
debug: jest.fn(),
} as unknown) as Logger;
beforeEach(async () => {
mockServer = new Hapi.Server({
debug: false,
port: 8080,
routes: { log: { collect: true } },
});
mockServer.config = () => ({ get: jest.fn(), has: jest.fn() });
mockReportingPlugin = await createMockReportingCore();
mockReportingPlugin.getEnqueueJob = async () =>
jest.fn().mockImplementation(() => ({ toJSON: () => '{ "job": "data" }' }));
});
const mockPlugins = {
elasticsearch: {
adminClient: { callAsInternalUser: jest.fn() },
},
security: null,
};
const getErrorsFromRequest = (request: Hapi.Request) => {
// @ts-ignore error property doesn't exist on RequestLog
return request.logs.filter(log => log.tags.includes('error')).map(log => log.error); // NOTE: error stack is available
};
test(`returns 400 if there are no job params`, async () => {
registerJobGenerationRoutes(
mockReportingPlugin,
(mockServer as unknown) as ServerFacade,
(mockPlugins as unknown) as ReportingSetupDeps,
mockLogger
);
const options = {
method: 'POST',
url: '/api/reporting/generate/printablePdf',
};
const { payload, request } = await mockServer.inject(options);
expect(payload).toMatchInlineSnapshot(
`"{\\"statusCode\\":400,\\"error\\":\\"Bad Request\\",\\"message\\":\\"A jobParams RISON string is required\\"}"`
);
const errorLogs = getErrorsFromRequest(request);
expect(errorLogs).toMatchInlineSnapshot(`
Array [
[Error: A jobParams RISON string is required],
]
`);
});
test(`returns 400 if job params is invalid`, async () => {
registerJobGenerationRoutes(
mockReportingPlugin,
(mockServer as unknown) as ServerFacade,
(mockPlugins as unknown) as ReportingSetupDeps,
mockLogger
);
const options = {
method: 'POST',
url: '/api/reporting/generate/printablePdf',
payload: { jobParams: `foo:` },
};
const { payload, request } = await mockServer.inject(options);
expect(payload).toMatchInlineSnapshot(
`"{\\"statusCode\\":400,\\"error\\":\\"Bad Request\\",\\"message\\":\\"invalid rison: foo:\\"}"`
);
const errorLogs = getErrorsFromRequest(request);
expect(errorLogs).toMatchInlineSnapshot(`
Array [
[Error: invalid rison: foo:],
]
`);
});
test(`returns 500 if job handler throws an error`, async () => {
mockReportingPlugin.getEnqueueJob = async () =>
jest.fn().mockImplementation(() => ({
toJSON: () => {
throw new Error('you found me');
},
}));
registerJobGenerationRoutes(
mockReportingPlugin,
(mockServer as unknown) as ServerFacade,
(mockPlugins as unknown) as ReportingSetupDeps,
mockLogger
);
const options = {
method: 'POST',
url: '/api/reporting/generate/printablePdf',
payload: { jobParams: `abc` },
};
const { payload, request } = await mockServer.inject(options);
expect(payload).toMatchInlineSnapshot(
`"{\\"statusCode\\":500,\\"error\\":\\"Internal Server Error\\",\\"message\\":\\"An internal server error occurred\\"}"`
);
const errorLogs = getErrorsFromRequest(request);
expect(errorLogs).toMatchInlineSnapshot(`
Array [
[Error: you found me],
[Error: you found me],
]
`);
});