Skip to content

Commit

Permalink
Merge branch 'master' into btsymbala/better-naming-for-field
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Oct 6, 2020
2 parents 4b5e99c + c240936 commit 72e020d
Show file tree
Hide file tree
Showing 194 changed files with 2,246 additions and 2,100 deletions.
1 change: 1 addition & 0 deletions docs/development/core/server/kibana-plugin-core-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [OnPreAuthToolkit](./kibana-plugin-core-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. |
| [OnPreResponseExtensions](./kibana-plugin-core-server.onpreresponseextensions.md) | Additional data to extend a response. |
| [OnPreResponseInfo](./kibana-plugin-core-server.onpreresponseinfo.md) | Response status code. |
| [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) | Additional data to extend a response when rendering a new body |
| [OnPreResponseToolkit](./kibana-plugin-core-server.onpreresponsetoolkit.md) | A tool set defining an outcome of OnPreResponse interceptor for incoming request. |
| [OnPreRoutingToolkit](./kibana-plugin-core-server.onpreroutingtoolkit.md) | A tool set defining an outcome of OnPreRouting interceptor for incoming request. |
| [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) | Regroups metrics gathered by all the collectors. This contains metrics about the os/runtime, the kibana process and the http server. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) &gt; [body](./kibana-plugin-core-server.onpreresponserender.body.md)

## OnPreResponseRender.body property

the body to use in the response

<b>Signature:</b>

```typescript
body: string;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) &gt; [headers](./kibana-plugin-core-server.onpreresponserender.headers.md)

## OnPreResponseRender.headers property

additional headers to attach to the response

<b>Signature:</b>

```typescript
headers?: ResponseHeaders;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md)

## OnPreResponseRender interface

Additional data to extend a response when rendering a new body

<b>Signature:</b>

```typescript
export interface OnPreResponseRender
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [body](./kibana-plugin-core-server.onpreresponserender.body.md) | <code>string</code> | the body to use in the response |
| [headers](./kibana-plugin-core-server.onpreresponserender.headers.md) | <code>ResponseHeaders</code> | additional headers to attach to the response |

Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ export interface OnPreResponseToolkit
| Property | Type | Description |
| --- | --- | --- |
| [next](./kibana-plugin-core-server.onpreresponsetoolkit.next.md) | <code>(responseExtensions?: OnPreResponseExtensions) =&gt; OnPreResponseResult</code> | To pass request to the next handler |
| [render](./kibana-plugin-core-server.onpreresponsetoolkit.render.md) | <code>(responseRender: OnPreResponseRender) =&gt; OnPreResponseResult</code> | To override the response with a different body |

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [OnPreResponseToolkit](./kibana-plugin-core-server.onpreresponsetoolkit.md) &gt; [render](./kibana-plugin-core-server.onpreresponsetoolkit.render.md)

## OnPreResponseToolkit.render property

To override the response with a different body

<b>Signature:</b>

```typescript
render: (responseRender: OnPreResponseRender) => OnPreResponseResult;
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@
"@babel/register": "^7.10.5",
"@babel/types": "^7.11.0",
"@elastic/apm-rum": "^5.6.1",
"@elastic/charts": "23.1.1",
"@elastic/charts": "23.2.1",
"@elastic/ems-client": "7.10.0",
"@elastic/eslint-config-kibana": "0.15.0",
"@elastic/eslint-plugin-eui": "0.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-ui-shared-deps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"kbn:watch": "node scripts/build --dev --watch"
},
"dependencies": {
"@elastic/charts": "23.1.1",
"@elastic/charts": "23.2.1",
"@elastic/eui": "29.3.0",
"@elastic/numeral": "^2.5.0",
"@kbn/i18n": "1.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/core/server/http/http_server.mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ type ToolkitMock = jest.Mocked<OnPreResponseToolkit & OnPostAuthToolkit & OnPreR

const createToolkitMock = (): ToolkitMock => {
return {
render: jest.fn(),
next: jest.fn(),
rewriteUrl: jest.fn(),
};
Expand Down
1 change: 1 addition & 0 deletions src/core/server/http/http_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ const createAuthToolkitMock = (): jest.Mocked<AuthToolkit> => ({
});

const createOnPreResponseToolkitMock = (): jest.Mocked<OnPreResponseToolkit> => ({
render: jest.fn(),
next: jest.fn(),
});

Expand Down
1 change: 1 addition & 0 deletions src/core/server/http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export { OnPreAuthHandler, OnPreAuthToolkit } from './lifecycle/on_pre_auth';
export {
OnPreResponseHandler,
OnPreResponseToolkit,
OnPreResponseRender,
OnPreResponseExtensions,
OnPreResponseInfo,
} from './lifecycle/on_pre_response';
Expand Down
61 changes: 61 additions & 0 deletions src/core/server/http/integration_tests/lifecycle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,67 @@ describe('OnPreResponse', () => {

expect(requestBody).toStrictEqual({});
});

it('supports rendering a different response body', async () => {
const { registerOnPreResponse, server: innerServer, createRouter } = await server.setup(
setupDeps
);
const router = createRouter('/');

router.get({ path: '/', validate: false }, (context, req, res) => {
return res.ok({
headers: {
'Original-Header-A': 'A',
},
body: 'original',
});
});

registerOnPreResponse((req, res, t) => {
return t.render({ body: 'overridden' });
});

await server.start();

const result = await supertest(innerServer.listener).get('/').expect(200, 'overridden');

expect(result.header['original-header-a']).toBe('A');
});

it('supports rendering a different response body + headers', async () => {
const { registerOnPreResponse, server: innerServer, createRouter } = await server.setup(
setupDeps
);
const router = createRouter('/');

router.get({ path: '/', validate: false }, (context, req, res) => {
return res.ok({
headers: {
'Original-Header-A': 'A',
'Original-Header-B': 'B',
},
body: 'original',
});
});

registerOnPreResponse((req, res, t) => {
return t.render({
headers: {
'Original-Header-A': 'AA',
'New-Header-C': 'C',
},
body: 'overridden',
});
});

await server.start();

const result = await supertest(innerServer.listener).get('/').expect(200, 'overridden');

expect(result.header['original-header-a']).toBe('AA');
expect(result.header['original-header-b']).toBe('B');
expect(result.header['new-header-c']).toBe('C');
});
});

describe('run interceptors in the right order', () => {
Expand Down
79 changes: 61 additions & 18 deletions src/core/server/http/lifecycle/on_pre_response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,23 @@
* under the License.
*/

import { Lifecycle, Request, ResponseToolkit as HapiResponseToolkit } from 'hapi';
import { Lifecycle, Request, ResponseObject, ResponseToolkit as HapiResponseToolkit } from 'hapi';
import Boom from 'boom';
import { Logger } from '../../logging';

import { HapiResponseAdapter, KibanaRequest, ResponseHeaders } from '../router';

enum ResultType {
render = 'render',
next = 'next',
}

interface Render {
type: ResultType.render;
body: string;
headers?: ResponseHeaders;
}

interface Next {
type: ResultType.next;
headers?: ResponseHeaders;
Expand All @@ -35,7 +42,18 @@ interface Next {
/**
* @internal
*/
type OnPreResponseResult = Next;
type OnPreResponseResult = Render | Next;

/**
* Additional data to extend a response when rendering a new body
* @public
*/
export interface OnPreResponseRender {
/** additional headers to attach to the response */
headers?: ResponseHeaders;
/** the body to use in the response */
body: string;
}

/**
* Additional data to extend a response.
Expand All @@ -55,6 +73,12 @@ export interface OnPreResponseInfo {
}

const preResponseResult = {
render(responseRender: OnPreResponseRender): OnPreResponseResult {
return { type: ResultType.render, body: responseRender.body, headers: responseRender?.headers };
},
isRender(result: OnPreResponseResult): result is Render {
return result && result.type === ResultType.render;
},
next(responseExtensions?: OnPreResponseExtensions): OnPreResponseResult {
return { type: ResultType.next, headers: responseExtensions?.headers };
},
Expand All @@ -68,11 +92,14 @@ const preResponseResult = {
* @public
*/
export interface OnPreResponseToolkit {
/** To override the response with a different body */
render: (responseRender: OnPreResponseRender) => OnPreResponseResult;
/** To pass request to the next handler */
next: (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult;
}

const toolkit: OnPreResponseToolkit = {
render: preResponseResult.render,
next: preResponseResult.next,
};

Expand Down Expand Up @@ -106,26 +133,36 @@ export function adoptToHapiOnPreResponseFormat(fn: OnPreResponseHandler, log: Lo
: response.statusCode;

const result = await fn(KibanaRequest.from(request), { statusCode }, toolkit);
if (!preResponseResult.isNext(result)) {

if (preResponseResult.isNext(result)) {
if (result.headers) {
if (isBoom(response)) {
findHeadersIntersection(response.output.headers, result.headers, log);
// hapi wraps all error response in Boom object internally
response.output.headers = {
...response.output.headers,
...(result.headers as any), // hapi types don't specify string[] as valid value
};
} else {
findHeadersIntersection(response.headers, result.headers, log);
setHeaders(response, result.headers);
}
}
} else if (preResponseResult.isRender(result)) {
const overriddenResponse = responseToolkit.response(result.body).code(statusCode);

const originalHeaders = isBoom(response) ? response.output.headers : response.headers;
setHeaders(overriddenResponse, originalHeaders);
if (result.headers) {
setHeaders(overriddenResponse, result.headers);
}

return overriddenResponse;
} else {
throw new Error(
`Unexpected result from OnPreResponse. Expected OnPreResponseResult, but given: ${result}.`
);
}
if (result.headers) {
if (isBoom(response)) {
findHeadersIntersection(response.output.headers, result.headers, log);
// hapi wraps all error response in Boom object internally
response.output.headers = {
...response.output.headers,
...(result.headers as any), // hapi types don't specify string[] as valid value
};
} else {
findHeadersIntersection(response.headers, result.headers, log);
for (const [headerName, headerValue] of Object.entries(result.headers)) {
response.header(headerName, headerValue as any); // hapi types don't specify string[] as valid value
}
}
}
}
} catch (error) {
log.error(error);
Expand All @@ -140,6 +177,12 @@ function isBoom(response: any): response is Boom {
return response instanceof Boom;
}

function setHeaders(response: ResponseObject, headers: ResponseHeaders) {
for (const [headerName, headerValue] of Object.entries(headers)) {
response.header(headerName, headerValue as any); // hapi types don't specify string[] as valid value
}
}

// NOTE: responseHeaders contains not a full list of response headers, but only explicitly set on a response object.
// any headers added by hapi internally, like `content-type`, `content-length`, etc. are not present here.
function findHeadersIntersection(
Expand Down
1 change: 1 addition & 0 deletions src/core/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export {
OnPostAuthToolkit,
OnPreResponseHandler,
OnPreResponseToolkit,
OnPreResponseRender,
OnPreResponseExtensions,
OnPreResponseInfo,
RedirectResponseOptions,
Expand Down
7 changes: 7 additions & 0 deletions src/core/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1530,9 +1530,16 @@ export interface OnPreResponseInfo {
statusCode: number;
}

// @public
export interface OnPreResponseRender {
body: string;
headers?: ResponseHeaders;
}

// @public
export interface OnPreResponseToolkit {
next: (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult;
render: (responseRender: OnPreResponseRender) => OnPreResponseResult;
}

// Warning: (ae-forgotten-export) The symbol "OnPreRoutingResult" needs to be exported by the entry point index.d.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import { i18n } from '@kbn/i18n';
import { AppMountParameters } from 'kibana/public';
import { ViewMode } from '../../embeddable_plugin';
import { TopNavIds } from './top_nav_ids';
import { NavAction } from '../../types';
Expand All @@ -31,7 +32,8 @@ import { NavAction } from '../../types';
export function getTopNavConfig(
dashboardMode: ViewMode,
actions: { [key: string]: NavAction },
hideWriteControls: boolean
hideWriteControls: boolean,
onAppLeave?: AppMountParameters['onAppLeave']
) {
switch (dashboardMode) {
case ViewMode.VIEW:
Expand Down
Loading

0 comments on commit 72e020d

Please sign in to comment.