mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Add FTR tests for stream/buffer error responses (#188937)
## Summary Fix https://github.com/elastic/kibana/issues/56305
This commit is contained in:
parent
1b45a27853
commit
85a90a71e4
6 changed files with 80 additions and 4 deletions
|
@ -115,7 +115,7 @@ export class HapiResponseAdapter {
|
|||
return response;
|
||||
}
|
||||
|
||||
private toError(kibanaResponse: KibanaResponse<ResponseError | Buffer | stream.Readable>) {
|
||||
private toError(kibanaResponse: KibanaResponse<ResponseError>) {
|
||||
const { payload } = kibanaResponse;
|
||||
|
||||
// Special case for when we are proxying requests and want to enable streaming back error responses opaquely.
|
||||
|
@ -153,7 +153,12 @@ function getErrorMessage(payload?: ResponseError): string {
|
|||
if (!payload) {
|
||||
throw new Error('expected error message to be provided');
|
||||
}
|
||||
if (typeof payload === 'string') return payload;
|
||||
if (typeof payload === 'string') {
|
||||
return payload;
|
||||
}
|
||||
if (isStreamOrBuffer(payload)) {
|
||||
throw new Error(`can't resolve error message from stream or buffer`);
|
||||
}
|
||||
// for ES response errors include nested error reason message. it doesn't contain sensitive data.
|
||||
if (isElasticsearchResponseError(payload)) {
|
||||
return `[${payload.message}]: ${
|
||||
|
@ -164,6 +169,10 @@ function getErrorMessage(payload?: ResponseError): string {
|
|||
return getErrorMessage(payload.message);
|
||||
}
|
||||
|
||||
function isStreamOrBuffer(payload: ResponseError): payload is stream.Stream | Buffer {
|
||||
return Buffer.isBuffer(payload) || stream.isReadable(payload as stream.Readable);
|
||||
}
|
||||
|
||||
function getErrorAttributes(payload?: ResponseError): ResponseErrorAttributes | undefined {
|
||||
return typeof payload === 'object' && 'attributes' in payload ? payload.attributes : undefined;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ export type ResponseErrorAttributes = Record<string, any>;
|
|||
*/
|
||||
export type ResponseError =
|
||||
| string
|
||||
| Buffer
|
||||
| Stream
|
||||
| Error
|
||||
| {
|
||||
message: string | Error;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { Stream } from 'stream';
|
||||
import type {
|
||||
CustomHttpResponseOptions,
|
||||
HttpResponseOptions,
|
||||
|
@ -139,7 +138,7 @@ export interface KibanaErrorResponseFactory {
|
|||
* Creates an error response with defined status code and payload.
|
||||
* @param options - {@link CustomHttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client
|
||||
*/
|
||||
customError(options: CustomHttpResponseOptions<ResponseError | Buffer | Stream>): IKibanaResponse;
|
||||
customError(options: CustomHttpResponseOptions<ResponseError>): IKibanaResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Readable } from 'stream';
|
||||
import type { Plugin, CoreSetup } from '@kbn/core/server';
|
||||
|
||||
export class CoreHttpPlugin implements Plugin {
|
||||
|
@ -87,6 +88,32 @@ export class CoreHttpPlugin implements Plugin {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
router.get(
|
||||
{
|
||||
path: '/api/core_http/error_stream',
|
||||
validate: false,
|
||||
},
|
||||
async (ctx, req, res) => {
|
||||
return res.customError({
|
||||
body: Readable.from(['error stream'], { objectMode: false }),
|
||||
statusCode: 501,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
router.get(
|
||||
{
|
||||
path: '/api/core_http/error_buffer',
|
||||
validate: false,
|
||||
},
|
||||
async (ctx, req, res) => {
|
||||
return res.customError({
|
||||
body: Buffer.from('error buffer', 'utf8'),
|
||||
statusCode: 501,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import '@kbn/core-provider-plugin/types';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
// routes defined in the `core_http` test plugin
|
||||
describe('Custom errors', () => {
|
||||
it('can serve an error response from stream', async () => {
|
||||
await supertest
|
||||
.get('/api/core_http/error_stream')
|
||||
.expect(501)
|
||||
.then((response) => {
|
||||
const res = response.body.toString();
|
||||
expect(res).to.eql('error stream');
|
||||
});
|
||||
});
|
||||
|
||||
it('can serve an error response from buffer', async () => {
|
||||
await supertest
|
||||
.get('/api/core_http/error_buffer')
|
||||
.expect(501)
|
||||
.then((response) => {
|
||||
const res = response.body.toString();
|
||||
expect(res).to.eql('error buffer');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -26,5 +26,6 @@ export default function ({ loadTestFile }: PluginFunctionalProviderContext) {
|
|||
loadTestFile(require.resolve('./http'));
|
||||
loadTestFile(require.resolve('./http_versioned'));
|
||||
loadTestFile(require.resolve('./dynamic_contract_resolving'));
|
||||
loadTestFile(require.resolve('./error_response'));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue