Skip to content

Commit

Permalink
Unify response interface in handler and request interceptors (#42442)
Browse files Browse the repository at this point in the history
* add response factory to the interceptors

* adopt x-pack code to the changes

* Add a separate response factory for lifecycles.

Only route handler can respond with 2xx response.
Interceptors may redirect or reject an incoming request.

* re-generate docs

* response.internal --> response.internalError

* use internalError for exceptions in authenticator

* before Security plugin proxied ES error status code. now sets explicitly.

* provide error via message field of error response for BWC

* update docs

* add customError response

* restore integration test and update unit tests

* update docs

* support Hapi error format for BWC

* add a couple of tests
  • Loading branch information
mshustov committed Aug 8, 2019
1 parent 35528af commit 06adc73
Show file tree
Hide file tree
Showing 44 changed files with 1,898 additions and 1,710 deletions.
Expand Up @@ -8,5 +8,5 @@
<b>Signature:</b>

```typescript
export declare type AuthenticationHandler = (request: KibanaRequest, t: AuthToolkit) => AuthResult | Promise<AuthResult>;
export declare type AuthenticationHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: AuthToolkit) => AuthResult | KibanaResponse | Promise<AuthResult | KibanaResponse>;
```
Expand Up @@ -17,6 +17,4 @@ export interface AuthToolkit
| Property | Type | Description |
| --- | --- | --- |
| [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) | <code>(data?: AuthResultParams) =&gt; AuthResult</code> | Authentication is successful with given credentials, allow request to pass through |
| [redirected](./kibana-plugin-server.authtoolkit.redirected.md) | <code>(url: string) =&gt; AuthResult</code> | Authentication requires to interrupt request handling and redirect to a configured url |
| [rejected](./kibana-plugin-server.authtoolkit.rejected.md) | <code>(error: Error, options?: {</code><br/><code> statusCode?: number;</code><br/><code> }) =&gt; AuthResult</code> | Authentication is unsuccessful, fail the request with specified error. |

This file was deleted.

This file was deleted.

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

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md)

## LifecycleResponseFactory type

Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client.

<b>Signature:</b>

```typescript
export declare type LifecycleResponseFactory = typeof lifecycleResponseFactory;
```
1 change: 1 addition & 0 deletions docs/development/core/server/kibana-plugin-server.md
Expand Up @@ -120,6 +120,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Return authentication status for a request. |
| [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. |
| [KnownHeaders](./kibana-plugin-server.knownheaders.md) | Set of well-known HTTP headers. |
| [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. |
| [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) | |
| [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) | |
| [PluginInitializer](./kibana-plugin-server.plugininitializer.md) | The <code>plugin</code> export at the root of a plugin's <code>server</code> directory should conform to this interface. |
Expand Down
Expand Up @@ -8,5 +8,5 @@
<b>Signature:</b>

```typescript
export declare type OnPostAuthHandler<Params = any, Query = any, Body = any> = (request: KibanaRequest<Params, Query, Body>, t: OnPostAuthToolkit) => OnPostAuthResult | Promise<OnPostAuthResult>;
export declare type OnPostAuthHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: OnPostAuthToolkit) => OnPostAuthResult | KibanaResponse | Promise<OnPostAuthResult | KibanaResponse>;
```
Expand Up @@ -17,6 +17,4 @@ export interface OnPostAuthToolkit
| Property | Type | Description |
| --- | --- | --- |
| [next](./kibana-plugin-server.onpostauthtoolkit.next.md) | <code>() =&gt; OnPostAuthResult</code> | To pass request to the next handler |
| [redirected](./kibana-plugin-server.onpostauthtoolkit.redirected.md) | <code>(url: string) =&gt; OnPostAuthResult</code> | To interrupt request handling and redirect to a configured url |
| [rejected](./kibana-plugin-server.onpostauthtoolkit.rejected.md) | <code>(error: Error, options?: {</code><br/><code> statusCode?: number;</code><br/><code> }) =&gt; OnPostAuthResult</code> | Fail the request with specified error. |

This file was deleted.

This file was deleted.

Expand Up @@ -8,5 +8,5 @@
<b>Signature:</b>

```typescript
export declare type OnPreAuthHandler<Params = any, Query = any, Body = any> = (request: KibanaRequest<Params, Query, Body>, t: OnPreAuthToolkit) => OnPreAuthResult | Promise<OnPreAuthResult>;
export declare type OnPreAuthHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: OnPreAuthToolkit) => OnPreAuthResult | KibanaResponse | Promise<OnPreAuthResult | KibanaResponse>;
```
Expand Up @@ -17,6 +17,5 @@ export interface OnPreAuthToolkit
| Property | Type | Description |
| --- | --- | --- |
| [next](./kibana-plugin-server.onpreauthtoolkit.next.md) | <code>() =&gt; OnPreAuthResult</code> | To pass request to the next handler |
| [redirected](./kibana-plugin-server.onpreauthtoolkit.redirected.md) | <code>(url: string, options?: {</code><br/><code> forward: boolean;</code><br/><code> }) =&gt; OnPreAuthResult</code> | To interrupt request handling and redirect to a configured url. If "options.forwarded" = true, request will be forwarded to another url right on the server. |
| [rejected](./kibana-plugin-server.onpreauthtoolkit.rejected.md) | <code>(error: Error, options?: {</code><br/><code> statusCode?: number;</code><br/><code> }) =&gt; OnPreAuthResult</code> | Fail the request with specified error. |
| [rewriteUrl](./kibana-plugin-server.onpreauthtoolkit.rewriteurl.md) | <code>(url: string) =&gt; OnPreAuthResult</code> | Rewrite requested resources url before is was authenticated and routed to a handler |

This file was deleted.

This file was deleted.

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

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) &gt; [rewriteUrl](./kibana-plugin-server.onpreauthtoolkit.rewriteurl.md)

## OnPreAuthToolkit.rewriteUrl property

Rewrite requested resources url before is was authenticated and routed to a handler

<b>Signature:</b>

```typescript
rewriteUrl: (url: string) => OnPreAuthResult;
```
Expand Up @@ -16,5 +16,5 @@ constructor(path: string);

| Parameter | Type | Description |
| --- | --- | --- |
| path | <code>string</code> | a router path, set as the very first path segment for all registered routes. |
| path | <code>string</code> | |

Expand Up @@ -23,7 +23,6 @@ export declare class Router
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [path](./kibana-plugin-server.router.path.md) | | <code>string</code> | |
| [routes](./kibana-plugin-server.router.routes.md) | | <code>Array&lt;Readonly&lt;RouterRoute&gt;&gt;</code> | |

## Methods

Expand Down
11 changes: 0 additions & 11 deletions docs/development/core/server/kibana-plugin-server.router.routes.md

This file was deleted.

40 changes: 34 additions & 6 deletions src/core/server/http/http_server.mocks.ts
Expand Up @@ -16,14 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Request, ResponseToolkit } from 'hapi';
import { Request } from 'hapi';
import { merge } from 'lodash';

import querystring from 'querystring';

import { schema } from '@kbn/config-schema';

import { KibanaRequest, RouteMethod } from './router';
import {
KibanaRequest,
LifecycleResponseFactory,
RouteMethod,
KibanaResponseFactory,
} from './router';

interface RequestFixtureOptions {
headers?: Record<string, string>;
Expand Down Expand Up @@ -97,12 +102,35 @@ function createRawRequestMock(customization: DeepPartial<Request> = {}) {
) as Request;
}

function createRawResponseToolkitMock(customization: DeepPartial<ResponseToolkit> = {}) {
return merge({}, customization) as ResponseToolkit;
}
const createResponseFactoryMock = (): jest.Mocked<KibanaResponseFactory> => ({
ok: jest.fn(),
accepted: jest.fn(),
noContent: jest.fn(),
custom: jest.fn(),
redirected: jest.fn(),
badRequest: jest.fn(),
unauthorized: jest.fn(),
forbidden: jest.fn(),
notFound: jest.fn(),
conflict: jest.fn(),
internalError: jest.fn(),
customError: jest.fn(),
});

const createLifecycleResponseFactoryMock = (): jest.Mocked<LifecycleResponseFactory> => ({
redirected: jest.fn(),
badRequest: jest.fn(),
unauthorized: jest.fn(),
forbidden: jest.fn(),
notFound: jest.fn(),
conflict: jest.fn(),
internalError: jest.fn(),
customError: jest.fn(),
});

export const httpServerMock = {
createKibanaRequest: createKibanaRequestMock,
createRawRequest: createRawRequestMock,
createRawResponseToolkit: createRawResponseToolkitMock,
createResponseFactory: createResponseFactoryMock,
createLifecycleResponseFactory: createLifecycleResponseFactoryMock,
};

0 comments on commit 06adc73

Please sign in to comment.