Skip to content

Commit

Permalink
Response factory parameters as named arguments (#43248)
Browse files Browse the repository at this point in the history
* pass body as response parameter. use attributes for error responses

* update core

* update tests

* update x-pack code

* update x-pack tests

* regen docs

* update comment

* Review feedback and fixes after master merge

* Eslint fixes
  • Loading branch information
mshustov authored and rudolf committed Aug 23, 2019
1 parent 182f4f3 commit 9a73201
Show file tree
Hide file tree
Showing 36 changed files with 460 additions and 354 deletions.
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-server](./kibana-plugin-server.md) &gt; [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) &gt; [body](./kibana-plugin-server.customhttpresponseoptions.body.md)

## CustomHttpResponseOptions.body property

HTTP message to send to the client

<b>Signature:</b>

```typescript
body?: T;
```
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-server](./kibana-plugin-server.md) &gt; [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) &gt; [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md)

## CustomHttpResponseOptions.headers property

HTTP Headers with additional information about response

<b>Signature:</b>

```typescript
headers?: ResponseHeaders;
```
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ HTTP response parameters for a response with adjustable status code.
<b>Signature:</b>

```typescript
export interface CustomHttpResponseOptions extends HttpResponseOptions
export interface CustomHttpResponseOptions<T extends HttpResponsePayload | ResponseError>
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [body](./kibana-plugin-server.customhttpresponseoptions.body.md) | <code>T</code> | HTTP message to send to the client |
| [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) | <code>ResponseHeaders</code> | HTTP Headers with additional information about response |
| [statusCode](./kibana-plugin-server.customhttpresponseoptions.statuscode.md) | <code>number</code> | |

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-server](./kibana-plugin-server.md) &gt; [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) &gt; [body](./kibana-plugin-server.errorhttpresponseoptions.body.md)

## ErrorHttpResponseOptions.body property

HTTP message to send to the client

<b>Signature:</b>

```typescript
body?: ResponseError;
```
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-server](./kibana-plugin-server.md) &gt; [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) &gt; [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md)

## ErrorHttpResponseOptions.headers property

HTTP Headers with additional information about 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-server](./kibana-plugin-server.md) &gt; [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md)

## ErrorHttpResponseOptions interface

HTTP response parameters

<b>Signature:</b>

```typescript
export interface ErrorHttpResponseOptions
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) | <code>ResponseError</code> | HTTP message to send to the client |
| [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) | <code>ResponseHeaders</code> | HTTP Headers with additional information about response |

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-server](./kibana-plugin-server.md) &gt; [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) &gt; [body](./kibana-plugin-server.httpresponseoptions.body.md)

## HttpResponseOptions.body property

HTTP message to send to the client

<b>Signature:</b>

```typescript
body?: HttpResponsePayload;
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ export interface HttpResponseOptions

| Property | Type | Description |
| --- | --- | --- |
| [body](./kibana-plugin-server.httpresponseoptions.body.md) | <code>HttpResponsePayload</code> | HTTP message to send to the client |
| [headers](./kibana-plugin-server.httpresponseoptions.headers.md) | <code>ResponseHeaders</code> | HTTP Headers with additional information about response |

Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ const validate = {
- Declare a function to respond to incoming request. The function will receive `request` object containing request details: url, headers, matched route, as well as validated `params`<!-- -->, `query`<!-- -->, `body`<!-- -->. And `response` object instructing HTTP server to create HTTP response with information sent back to the client as the response body, headers, and HTTP status. Unlike, `hapi` route handler in the Legacy platform, any exception raised during the handler call will generate `500 Server error` response and log error details for further investigation. See below for returning custom error responses.
```ts
const handler = async (request: KibanaRequest, response: ResponseFactory) => {
const handler = async (context: RequestHandlerContext, request: KibanaRequest, response: ResponseFactory) => {
const data = await findObject(request.params.id);
// creates a command to respond with 'not found' error
if (!data) return response.notFound();
// creates a command to send found data to the client and set response headers
return response.ok(data, {
return response.ok({
body: data,
headers: {
'content-type': 'application/json'
}
Expand All @@ -80,7 +81,8 @@ router.get({
async (context, request, response) => {
const data = await findObject(request.params.id);
if (!data) return response.notFound();
return response.ok(data, {
return response.ok({
body: data,
headers: {
'content-type': 'application/json'
}
Expand Down
4 changes: 3 additions & 1 deletion docs/development/core/server/kibana-plugin-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. |
| [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | |
| [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | |
| [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) | HTTP response parameters |
| [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. |
| [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters |
| [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) | Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to <code>hapi</code> server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. |
Expand All @@ -67,7 +68,6 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | |
| [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) | |
| [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) | Plugin specific context passed to a route handler. |
| [ResponseErrorMeta](./kibana-plugin-server.responseerrormeta.md) | Additional metadata to enhance error output or provide error details. |
| [RouteConfig](./kibana-plugin-server.routeconfig.md) | Route specific configuration. |
| [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) | Additional route options. |
| [SavedObject](./kibana-plugin-server.savedobject.md) | |
Expand Down Expand Up @@ -141,6 +141,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md) | Parameters passed to the request handler function. |
| [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md) | Expected outcome the request handler function. |
| [ResponseError](./kibana-plugin-server.responseerror.md) | Error message and optional data send to the client in case of error. |
| [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) | Additional data to provide error details. |
| [ResponseHeaders](./kibana-plugin-server.responseheaders.md) | Http response headers to set. |
| [RouteMethod](./kibana-plugin-server.routemethod.md) | The set of common HTTP methods supported by Kibana routing. |
| [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | |
| [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.<!-- -->\#\# SavedObjectsClient errors<!-- -->Since the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:<!-- -->1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md)<!-- -->Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the <code>isXYZError()</code> helpers exposed at <code>SavedObjectsErrorHelpers</code> should be used to understand and manage error responses from the <code>SavedObjectsClient</code>.<!-- -->Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for <code>error.body.error.type</code> or doing substring checks on <code>error.body.error.reason</code>, just use the helpers to understand the meaning of the error:<!-- -->\`\`\`<!-- -->js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }<!-- -->if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }<!-- -->// always rethrow the error unless you handle it throw error; \`\`\`<!-- -->\#\#\# 404s from missing index<!-- -->From the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.<!-- -->At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.<!-- -->From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.<!-- -->\#\#\# 503s from missing index<!-- -->Unlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's <code>action.auto_create_index</code> setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated.<!-- -->See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ Error message and optional data send to the client in case of error.
```typescript
export declare type ResponseError = string | Error | {
message: string | Error;
meta?: ResponseErrorMeta;
attributes?: ResponseErrorAttributes;
};
```
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-server](./kibana-plugin-server.md) &gt; [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md)

## ResponseErrorAttributes type

Additional data to provide error details.

<b>Signature:</b>

```typescript
export declare type ResponseErrorAttributes = Record<string, any>;
```

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

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

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

## ResponseHeaders type

Http response headers to set.

<b>Signature:</b>

```typescript
export declare type ResponseHeaders = {
[header in KnownHeaders]?: string | string[];
} & {
[header: string]: string | string[];
};
```
10 changes: 5 additions & 5 deletions src/core/server/http/cookie_sesson_storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ describe('Cookie based SessionStorage', () => {
const sessionValue = await sessionStorage.get();
if (!sessionValue) {
sessionStorage.set({ value: userData, expires: Date.now() + sessionDurationMs });
return res.ok({});
return res.ok();
}
return res.ok({ value: sessionValue.value });
return res.ok({ body: { value: sessionValue.value } });
});

const factory = await createCookieSessionStorageFactory(
Expand Down Expand Up @@ -180,7 +180,7 @@ describe('Cookie based SessionStorage', () => {
router.get({ path: '/', validate: false }, async (context, req, res) => {
const sessionStorage = factory.asScoped(req);
const sessionValue = await sessionStorage.get();
return res.ok({ value: sessionValue });
return res.ok({ body: { value: sessionValue } });
});

const factory = await createCookieSessionStorageFactory(
Expand Down Expand Up @@ -209,10 +209,10 @@ describe('Cookie based SessionStorage', () => {
if (!setOnce) {
setOnce = true;
sessionStorage.set({ value: userData, expires: Date.now() + sessionDurationMs });
return res.ok({ value: userData });
return res.ok({ body: { value: userData } });
}
const sessionValue = await sessionStorage.get();
return res.ok({ value: sessionValue });
return res.ok({ body: { value: sessionValue } });
});

const factory = await createCookieSessionStorageFactory(
Expand Down

0 comments on commit 9a73201

Please sign in to comment.