diff --git a/docs/development/core/public/kibana-plugin-public.httpbody.md b/docs/development/core/public/kibana-plugin-public.httpbody.md
deleted file mode 100644
index ab31f28b8dc38..0000000000000
--- a/docs/development/core/public/kibana-plugin-public.httpbody.md
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpBody](./kibana-plugin-public.httpbody.md)
-
-## HttpBody type
-
-
-Signature:
-
-```typescript
-export declare type HttpBody = BodyInit | null | any;
-```
diff --git a/docs/development/core/public/kibana-plugin-public.httperrorresponse.md b/docs/development/core/public/kibana-plugin-public.httperrorresponse.md
index aa669df796a09..5b1ee898a444d 100644
--- a/docs/development/core/public/kibana-plugin-public.httperrorresponse.md
+++ b/docs/development/core/public/kibana-plugin-public.httperrorresponse.md
@@ -8,7 +8,7 @@
Signature:
```typescript
-export interface HttpErrorResponse extends HttpResponse
+export interface HttpErrorResponse extends IHttpResponse
```
## Properties
diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md
new file mode 100644
index 0000000000000..250cf83309b3c
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [asResponse](./kibana-plugin-public.httpfetchoptions.asresponse.md)
+
+## HttpFetchOptions.asResponse property
+
+When `true` the return type of [HttpHandler](./kibana-plugin-public.httphandler.md) will be an [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) with detailed request and response information. When `false`, the return type will just be the parsed response body. Defaults to `false`.
+
+Signature:
+
+```typescript
+asResponse?: boolean;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md
index eca29b37425e9..6a0c4a8a7f137 100644
--- a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md
+++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md
@@ -16,6 +16,7 @@ export interface HttpFetchOptions extends HttpRequestInit
| Property | Type | Description |
| --- | --- | --- |
+| [asResponse](./kibana-plugin-public.httpfetchoptions.asresponse.md) | boolean
| When true
the return type of [HttpHandler](./kibana-plugin-public.httphandler.md) will be an [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) with detailed request and response information. When false
, the return type will just be the parsed response body. Defaults to false
. |
| [headers](./kibana-plugin-public.httpfetchoptions.headers.md) | HttpHeadersInit
| Headers to send with the request. See [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md). |
| [prependBasePath](./kibana-plugin-public.httpfetchoptions.prependbasepath.md) | boolean
| Whether or not the request should automatically prepend the basePath. Defaults to true
. |
| [query](./kibana-plugin-public.httpfetchoptions.query.md) | HttpFetchQuery
| The query string for an HTTP request. See [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md). |
diff --git a/docs/development/core/public/kibana-plugin-public.httphandler.md b/docs/development/core/public/kibana-plugin-public.httphandler.md
index 80fd1ea2e5761..89458c4743cd6 100644
--- a/docs/development/core/public/kibana-plugin-public.httphandler.md
+++ b/docs/development/core/public/kibana-plugin-public.httphandler.md
@@ -2,12 +2,12 @@
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpHandler](./kibana-plugin-public.httphandler.md)
-## HttpHandler type
+## HttpHandler interface
-A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [HttpBody](./kibana-plugin-public.httpbody.md) for the response.
+A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) for the response.
Signature:
```typescript
-export declare type HttpHandler = (path: string, options?: HttpFetchOptions) => Promise;
+export interface HttpHandler
```
diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md
index ca43ea31f0e2e..3a67dcbad3119 100644
--- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md
+++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md
@@ -9,17 +9,17 @@ Define an interceptor to be executed after a response is received.
Signature:
```typescript
-response?(httpResponse: HttpResponse, controller: IHttpInterceptController): Promise | InterceptedHttpResponse | void;
+response?(httpResponse: IHttpResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| httpResponse | HttpResponse
| |
+| httpResponse | IHttpResponse
| |
| controller | IHttpInterceptController
| |
Returns:
-`Promise | InterceptedHttpResponse | void`
+`Promise | IHttpResponseInterceptorOverrides | void`
diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md
index b8abd50e45461..476ceba649d40 100644
--- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md
+++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md
@@ -9,7 +9,7 @@ Define an interceptor to be executed if a response interceptor throws an error o
Signature:
```typescript
-responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController): Promise | InterceptedHttpResponse | void;
+responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void;
```
## Parameters
@@ -21,5 +21,5 @@ responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptC
Returns:
-`Promise | InterceptedHttpResponse | void`
+`Promise | IHttpResponseInterceptorOverrides | void`
diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.md b/docs/development/core/public/kibana-plugin-public.httpresponse.md
deleted file mode 100644
index e44515cc8a1e0..0000000000000
--- a/docs/development/core/public/kibana-plugin-public.httpresponse.md
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md)
-
-## HttpResponse interface
-
-
-Signature:
-
-```typescript
-export interface HttpResponse extends InterceptedHttpResponse
-```
-
-## Properties
-
-| Property | Type | Description |
-| --- | --- | --- |
-| [request](./kibana-plugin-public.httpresponse.request.md) | Readonly<Request>
| |
-
diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.request.md b/docs/development/core/public/kibana-plugin-public.httpresponse.request.md
deleted file mode 100644
index 84ab1bc7af853..0000000000000
--- a/docs/development/core/public/kibana-plugin-public.httpresponse.request.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md) > [request](./kibana-plugin-public.httpresponse.request.md)
-
-## HttpResponse.request property
-
-Signature:
-
-```typescript
-request: Readonly;
-```
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.body.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.body.md
new file mode 100644
index 0000000000000..2f8710ccdc60e
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponse.body.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) > [body](./kibana-plugin-public.ihttpresponse.body.md)
+
+## IHttpResponse.body property
+
+Parsed body received, may be undefined if there was an error.
+
+Signature:
+
+```typescript
+readonly body?: TResponseBody;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.md
new file mode 100644
index 0000000000000..5ddce0ba2d0f1
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponse.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md)
+
+## IHttpResponse interface
+
+
+Signature:
+
+```typescript
+export interface IHttpResponse
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [body](./kibana-plugin-public.ihttpresponse.body.md) | TResponseBody
| Parsed body received, may be undefined if there was an error. |
+| [request](./kibana-plugin-public.ihttpresponse.request.md) | Readonly<Request>
| Raw request sent to Kibana server. |
+| [response](./kibana-plugin-public.ihttpresponse.response.md) | Readonly<Response>
| Raw response received, may be undefined if there was an error. |
+
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.request.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.request.md
new file mode 100644
index 0000000000000..12e5405eb5ed4
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponse.request.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) > [request](./kibana-plugin-public.ihttpresponse.request.md)
+
+## IHttpResponse.request property
+
+Raw request sent to Kibana server.
+
+Signature:
+
+```typescript
+readonly request: Readonly;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.response.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.response.md
new file mode 100644
index 0000000000000..9d0b4b59a638d
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponse.response.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) > [response](./kibana-plugin-public.ihttpresponse.response.md)
+
+## IHttpResponse.response property
+
+Raw response received, may be undefined if there was an error.
+
+Signature:
+
+```typescript
+readonly response?: Readonly;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md
new file mode 100644
index 0000000000000..36fcfb390617c
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) > [body](./kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md)
+
+## IHttpResponseInterceptorOverrides.body property
+
+Parsed body received, may be undefined if there was an error.
+
+Signature:
+
+```typescript
+readonly body?: TResponseBody;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md
new file mode 100644
index 0000000000000..44f067c429e98
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md)
+
+## IHttpResponseInterceptorOverrides interface
+
+Properties that can be returned by HttpInterceptor.request to override the response.
+
+Signature:
+
+```typescript
+export interface IHttpResponseInterceptorOverrides
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [body](./kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md) | TResponseBody
| Parsed body received, may be undefined if there was an error. |
+| [response](./kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md) | Readonly<Response>
| Raw response received, may be undefined if there was an error. |
+
diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md
new file mode 100644
index 0000000000000..bcba996645ba6
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) > [response](./kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md)
+
+## IHttpResponseInterceptorOverrides.response property
+
+Raw response received, may be undefined if there was an error.
+
+Signature:
+
+```typescript
+readonly response?: Readonly;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.body.md b/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.body.md
deleted file mode 100644
index fc6d34c0b74f2..0000000000000
--- a/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.body.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [InterceptedHttpResponse](./kibana-plugin-public.interceptedhttpresponse.md) > [body](./kibana-plugin-public.interceptedhttpresponse.body.md)
-
-## InterceptedHttpResponse.body property
-
-Signature:
-
-```typescript
-body?: HttpBody;
-```
diff --git a/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.md b/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.md
deleted file mode 100644
index c4a7f4d6b2afa..0000000000000
--- a/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [InterceptedHttpResponse](./kibana-plugin-public.interceptedhttpresponse.md)
-
-## InterceptedHttpResponse interface
-
-
-Signature:
-
-```typescript
-export interface InterceptedHttpResponse
-```
-
-## Properties
-
-| Property | Type | Description |
-| --- | --- | --- |
-| [body](./kibana-plugin-public.interceptedhttpresponse.body.md) | HttpBody
| |
-| [response](./kibana-plugin-public.interceptedhttpresponse.response.md) | Response
| |
-
diff --git a/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.response.md b/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.response.md
deleted file mode 100644
index dceb55113ee78..0000000000000
--- a/docs/development/core/public/kibana-plugin-public.interceptedhttpresponse.response.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [InterceptedHttpResponse](./kibana-plugin-public.interceptedhttpresponse.md) > [response](./kibana-plugin-public.interceptedhttpresponse.response.md)
-
-## InterceptedHttpResponse.response property
-
-Signature:
-
-```typescript
-response?: Response;
-```
diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md
index f527c92d070de..22b6f7faf2daa 100644
--- a/docs/development/core/public/kibana-plugin-public.md
+++ b/docs/development/core/public/kibana-plugin-public.md
@@ -52,10 +52,10 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [HttpErrorResponse](./kibana-plugin-public.httperrorresponse.md) | |
| [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). |
| [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) | |
+| [HttpHandler](./kibana-plugin-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) for the response. |
| [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | |
| [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) | An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). |
| [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) | Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. |
-| [HttpResponse](./kibana-plugin-public.httpresponse.md) | |
| [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) | |
| [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. |
| [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication |
@@ -63,7 +63,8 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. |
| [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) | |
| [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) | Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). |
-| [InterceptedHttpResponse](./kibana-plugin-public.interceptedhttpresponse.md) | |
+| [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) | |
+| [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. |
| [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) |
| [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform
module. |
| [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform
module. |
@@ -108,8 +109,6 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. |
| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) |
| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). |
-| [HttpBody](./kibana-plugin-public.httpbody.md) | |
-| [HttpHandler](./kibana-plugin-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [HttpBody](./kibana-plugin-public.httpbody.md) for the response. |
| [HttpSetup](./kibana-plugin-public.httpsetup.md) | See [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) |
| [HttpStart](./kibana-plugin-public.httpstart.md) | See [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) |
| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx
index e330a4b0326ae..24d9765953c44 100644
--- a/src/core/public/application/capabilities/capabilities_service.tsx
+++ b/src/core/public/application/capabilities/capabilities_service.tsx
@@ -74,7 +74,7 @@ export class CapabilitiesService {
const url = http.anonymousPaths.isAnonymous(window.location.pathname)
? '/api/core/capabilities/defaults'
: '/api/core/capabilities';
- const capabilities = await http.post(url, {
+ const capabilities = await http.post(url, {
body: payload,
});
return deepFreeze(capabilities);
diff --git a/src/core/public/http/fetch.ts b/src/core/public/http/fetch.ts
new file mode 100644
index 0000000000000..472b617cacd7f
--- /dev/null
+++ b/src/core/public/http/fetch.ts
@@ -0,0 +1,155 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { merge } from 'lodash';
+import { format } from 'url';
+
+import { IBasePath, HttpInterceptor, HttpHandler, HttpFetchOptions, IHttpResponse } from './types';
+import { HttpFetchError } from './http_fetch_error';
+import { HttpInterceptController } from './http_intercept_controller';
+import { HttpResponse } from './response';
+import { interceptRequest, interceptResponse } from './intercept';
+import { HttpInterceptHaltError } from './http_intercept_halt_error';
+
+interface Params {
+ basePath: IBasePath;
+ kibanaVersion: string;
+}
+
+const JSON_CONTENT = /^(application\/(json|x-javascript)|text\/(x-)?javascript|x-json)(;.*)?$/;
+const NDJSON_CONTENT = /^(application\/ndjson)(;.*)?$/;
+
+export class FetchService {
+ private readonly interceptors = new Set();
+
+ constructor(private readonly params: Params) {}
+
+ public intercept(interceptor: HttpInterceptor) {
+ this.interceptors.add(interceptor);
+ return () => this.interceptors.delete(interceptor);
+ }
+
+ public removeAllInterceptors() {
+ this.interceptors.clear();
+ }
+
+ public fetch: HttpHandler = async (
+ path: string,
+ options: HttpFetchOptions = {}
+ ) => {
+ const initialRequest = this.createRequest(path, options);
+ const controller = new HttpInterceptController();
+
+ // We wrap the interception in a separate promise to ensure that when
+ // a halt is called we do not resolve or reject, halting handling of the promise.
+ return new Promise>(async (resolve, reject) => {
+ try {
+ const interceptedRequest = await interceptRequest(
+ initialRequest,
+ this.interceptors,
+ controller
+ );
+ const initialResponse = this.fetchResponse(interceptedRequest);
+ const interceptedResponse = await interceptResponse(
+ initialResponse,
+ this.interceptors,
+ controller
+ );
+
+ if (options.asResponse) {
+ resolve(interceptedResponse);
+ } else {
+ resolve(interceptedResponse.body);
+ }
+ } catch (error) {
+ if (!(error instanceof HttpInterceptHaltError)) {
+ reject(error);
+ }
+ }
+ });
+ };
+
+ private createRequest(path: string, options?: HttpFetchOptions): Request {
+ // Merge and destructure options out that are not applicable to the Fetch API.
+ const { query, prependBasePath: shouldPrependBasePath, asResponse, ...fetchOptions } = merge(
+ {
+ method: 'GET',
+ credentials: 'same-origin',
+ prependBasePath: true,
+ headers: {
+ 'kbn-version': this.params.kibanaVersion,
+ 'Content-Type': 'application/json',
+ },
+ },
+ options || {}
+ );
+ const url = format({
+ pathname: shouldPrependBasePath ? this.params.basePath.prepend(path) : path,
+ query,
+ });
+
+ if (
+ options &&
+ options.headers &&
+ 'Content-Type' in options.headers &&
+ options.headers['Content-Type'] === undefined
+ ) {
+ delete fetchOptions.headers['Content-Type'];
+ }
+
+ return new Request(url, fetchOptions);
+ }
+
+ private async fetchResponse(request: Request) {
+ let response: Response;
+ let body = null;
+
+ try {
+ response = await window.fetch(request);
+ } catch (err) {
+ throw new HttpFetchError(err.message, request);
+ }
+
+ const contentType = response.headers.get('Content-Type') || '';
+
+ try {
+ if (NDJSON_CONTENT.test(contentType)) {
+ body = await response.blob();
+ } else if (JSON_CONTENT.test(contentType)) {
+ body = await response.json();
+ } else {
+ const text = await response.text();
+
+ try {
+ body = JSON.parse(text);
+ } catch (err) {
+ body = text;
+ }
+ }
+ } catch (err) {
+ throw new HttpFetchError(err.message, request, response, body);
+ }
+
+ if (!response.ok) {
+ throw new HttpFetchError(response.statusText, request, response, body);
+ }
+
+ return new HttpResponse({ request, response, body });
+ }
+}
diff --git a/src/core/public/http/http_service.test.ts b/src/core/public/http/http_service.test.ts
index 13906b91ed8df..09f3cca419e4d 100644
--- a/src/core/public/http/http_service.test.ts
+++ b/src/core/public/http/http_service.test.ts
@@ -24,7 +24,7 @@ import fetchMock from 'fetch-mock/es5/client';
import { readFileSync } from 'fs';
import { join } from 'path';
import { setup, SetupTap } from '../../../test_utils/public/http_test_setup';
-import { HttpResponse } from './types';
+import { IHttpResponse } from './types';
function delay(duration: number) {
return new Promise(r => setTimeout(r, duration));
@@ -101,32 +101,32 @@ describe('http requests', () => {
it('should return response', async () => {
const { http } = setup();
-
fetchMock.get('*', { foo: 'bar' });
-
const json = await http.fetch('/my/path');
-
expect(json).toEqual({ foo: 'bar' });
});
it('should prepend url with basepath by default', async () => {
const { http } = setup();
-
fetchMock.get('*', {});
await http.fetch('/my/path');
-
expect(fetchMock.lastUrl()).toBe('http://localhost/myBase/my/path');
});
it('should not prepend url with basepath when disabled', async () => {
const { http } = setup();
-
fetchMock.get('*', {});
await http.fetch('my/path', { prependBasePath: false });
-
expect(fetchMock.lastUrl()).toBe('/my/path');
});
+ it('should not include undefined query params', async () => {
+ const { http } = setup();
+ fetchMock.get('*', {});
+ await http.fetch('/my/path', { query: { a: undefined } });
+ expect(fetchMock.lastUrl()).toBe('http://localhost/myBase/my/path');
+ });
+
it('should make request with defaults', async () => {
const { http } = setup();
@@ -145,6 +145,18 @@ describe('http requests', () => {
});
});
+ it('should expose detailed response object when asResponse = true', async () => {
+ const { http } = setup();
+
+ fetchMock.get('*', { foo: 'bar' });
+
+ const response = await http.fetch('/my/path', { asResponse: true });
+
+ expect(response.request).toBeInstanceOf(Request);
+ expect(response.response).toBeInstanceOf(Response);
+ expect(response.body).toEqual({ foo: 'bar' });
+ });
+
it('should reject on network error', async () => {
const { http } = setup();
@@ -496,7 +508,7 @@ describe('interception', () => {
it('should accumulate response information', async () => {
const bodies = ['alpha', 'beta', 'gamma'];
- const createResponse = jest.fn((httpResponse: HttpResponse) => ({
+ const createResponse = jest.fn((httpResponse: IHttpResponse) => ({
body: bodies.shift(),
}));
diff --git a/src/core/public/http/http_setup.ts b/src/core/public/http/http_setup.ts
index 602382e3a5a60..c63750849f13a 100644
--- a/src/core/public/http/http_setup.ts
+++ b/src/core/public/http/http_setup.ts
@@ -27,21 +27,16 @@ import {
takeUntil,
tap,
} from 'rxjs/operators';
-import { merge } from 'lodash';
-import { format } from 'url';
import { InjectedMetadataSetup } from '../injected_metadata';
import { FatalErrorsSetup } from '../fatal_errors';
-import { HttpFetchOptions, HttpServiceBase, HttpInterceptor, HttpResponse } from './types';
+import { HttpFetchOptions, HttpServiceBase } from './types';
import { HttpInterceptController } from './http_intercept_controller';
-import { HttpFetchError } from './http_fetch_error';
import { HttpInterceptHaltError } from './http_intercept_halt_error';
import { BasePath } from './base_path_service';
import { AnonymousPaths } from './anonymous_paths';
+import { FetchService } from './fetch';
-const JSON_CONTENT = /^(application\/(json|x-javascript)|text\/(x-)?javascript|x-json)(;.*)?$/;
-const NDJSON_CONTENT = /^(application\/ndjson)(;.*)?$/;
-
-function checkHalt(controller: HttpInterceptController, error?: Error) {
+export function checkHalt(controller: HttpInterceptController, error?: Error) {
if (error instanceof HttpInterceptHaltError) {
throw error;
} else if (controller.halted) {
@@ -55,224 +50,15 @@ export const setup = (
): HttpServiceBase => {
const loadingCount$ = new BehaviorSubject(0);
const stop$ = new Subject();
- const interceptors = new Set();
const kibanaVersion = injectedMetadata.getKibanaVersion();
const basePath = new BasePath(injectedMetadata.getBasePath());
const anonymousPaths = new AnonymousPaths(basePath);
- function intercept(interceptor: HttpInterceptor) {
- interceptors.add(interceptor);
-
- return () => interceptors.delete(interceptor);
- }
-
- function removeAllInterceptors() {
- interceptors.clear();
- }
-
- function createRequest(path: string, options?: HttpFetchOptions) {
- const { query, prependBasePath: shouldPrependBasePath, ...fetchOptions } = merge(
- {
- method: 'GET',
- credentials: 'same-origin',
- prependBasePath: true,
- headers: {
- 'kbn-version': kibanaVersion,
- 'Content-Type': 'application/json',
- },
- },
- options || {}
- );
- const url = format({
- pathname: shouldPrependBasePath ? basePath.prepend(path) : path,
- query,
- });
-
- if (
- options &&
- options.headers &&
- 'Content-Type' in options.headers &&
- options.headers['Content-Type'] === undefined
- ) {
- delete fetchOptions.headers['Content-Type'];
- }
-
- return new Request(url, fetchOptions);
- }
-
- // Request/response interceptors are called in opposite orders.
- // Request hooks start from the newest interceptor and end with the oldest.
- function interceptRequest(
- request: Request,
- controller: HttpInterceptController
- ): Promise {
- let next = request;
-
- return [...interceptors].reduceRight(
- (promise, interceptor) =>
- promise.then(
- async (current: Request) => {
- next = current;
- checkHalt(controller);
-
- if (!interceptor.request) {
- return current;
- }
-
- return (await interceptor.request(current, controller)) || current;
- },
- async error => {
- checkHalt(controller, error);
-
- if (!interceptor.requestError) {
- throw error;
- }
-
- const nextRequest = await interceptor.requestError(
- { error, request: next },
- controller
- );
-
- if (!nextRequest) {
- throw error;
- }
-
- next = nextRequest;
- return next;
- }
- ),
- Promise.resolve(request)
- );
- }
-
- // Response hooks start from the oldest interceptor and end with the newest.
- async function interceptResponse(
- responsePromise: Promise,
- controller: HttpInterceptController
- ) {
- let current: HttpResponse | undefined;
-
- const finalHttpResponse = await [...interceptors].reduce(
- (promise, interceptor) =>
- promise.then(
- async httpResponse => {
- current = httpResponse;
- checkHalt(controller);
-
- if (!interceptor.response) {
- return httpResponse;
- }
-
- return {
- ...httpResponse,
- ...((await interceptor.response(httpResponse, controller)) || {}),
- };
- },
- async error => {
- const request = error.request || (current && current.request);
-
- checkHalt(controller, error);
-
- if (!interceptor.responseError) {
- throw error;
- }
-
- try {
- const next = await interceptor.responseError(
- {
- error,
- request,
- response: error.response || (current && current.response),
- body: error.body || (current && current.body),
- },
- controller
- );
-
- checkHalt(controller, error);
-
- if (!next) {
- throw error;
- }
-
- return { ...next, request };
- } catch (err) {
- checkHalt(controller, err);
- throw err;
- }
- }
- ),
- responsePromise
- );
-
- return finalHttpResponse.body;
- }
-
- async function fetcher(request: Request): Promise {
- let response;
- let body = null;
-
- try {
- response = await window.fetch(request);
- } catch (err) {
- throw new HttpFetchError(err.message, request);
- }
-
- const contentType = response.headers.get('Content-Type') || '';
-
- try {
- if (NDJSON_CONTENT.test(contentType)) {
- body = await response.blob();
- } else if (JSON_CONTENT.test(contentType)) {
- body = await response.json();
- } else {
- const text = await response.text();
-
- try {
- body = JSON.parse(text);
- } catch (err) {
- body = text;
- }
- }
- } catch (err) {
- throw new HttpFetchError(err.message, request, response, body);
- }
-
- if (!response.ok) {
- throw new HttpFetchError(response.statusText, request, response, body);
- }
-
- return { response, body, request };
- }
-
- async function fetch(path: string, options: HttpFetchOptions = {}) {
- const controller = new HttpInterceptController();
- const initialRequest = createRequest(path, options);
-
- // We wrap the interception in a separate promise to ensure that when
- // a halt is called we do not resolve or reject, halting handling of the promise.
- return new Promise(async (resolve, reject) => {
- function rejectIfNotHalted(err: any) {
- if (!(err instanceof HttpInterceptHaltError)) {
- reject(err);
- }
- }
-
- try {
- const request = await interceptRequest(initialRequest, controller);
-
- try {
- resolve(await interceptResponse(fetcher(request), controller));
- } catch (err) {
- rejectIfNotHalted(err);
- }
- } catch (err) {
- rejectIfNotHalted(err);
- }
- });
- }
+ const fetchService = new FetchService({ basePath, kibanaVersion });
function shorthand(method: string) {
- return (path: string, options: HttpFetchOptions = {}) => fetch(path, { ...options, method });
+ return (path: string, options: HttpFetchOptions = {}) =>
+ fetchService.fetch(path, { ...options, method });
}
function stop() {
@@ -321,9 +107,9 @@ export const setup = (
stop,
basePath,
anonymousPaths,
- intercept,
- removeAllInterceptors,
- fetch,
+ intercept: fetchService.intercept.bind(fetchService),
+ removeAllInterceptors: fetchService.removeAllInterceptors.bind(fetchService),
+ fetch: fetchService.fetch.bind(fetchService),
delete: shorthand('DELETE'),
get: shorthand('GET'),
head: shorthand('HEAD'),
diff --git a/src/core/public/http/intercept.ts b/src/core/public/http/intercept.ts
new file mode 100644
index 0000000000000..e2a16565c61c4
--- /dev/null
+++ b/src/core/public/http/intercept.ts
@@ -0,0 +1,134 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { HttpInterceptController } from './http_intercept_controller';
+import { HttpInterceptHaltError } from './http_intercept_halt_error';
+import { HttpInterceptor, IHttpResponse } from './types';
+import { HttpResponse } from './response';
+
+export async function interceptRequest(
+ request: Request,
+ interceptors: ReadonlySet,
+ controller: HttpInterceptController
+): Promise {
+ let next = request;
+
+ return [...interceptors].reduceRight(
+ (promise, interceptor) =>
+ promise.then(
+ async (current: Request) => {
+ next = current;
+ checkHalt(controller);
+
+ if (!interceptor.request) {
+ return current;
+ }
+
+ return (await interceptor.request(current, controller)) || current;
+ },
+ async error => {
+ checkHalt(controller, error);
+
+ if (!interceptor.requestError) {
+ throw error;
+ }
+
+ const nextRequest = await interceptor.requestError({ error, request: next }, controller);
+
+ if (!nextRequest) {
+ throw error;
+ }
+
+ next = nextRequest;
+ return next;
+ }
+ ),
+ Promise.resolve(request)
+ );
+}
+
+export async function interceptResponse(
+ responsePromise: Promise,
+ interceptors: ReadonlySet,
+ controller: HttpInterceptController
+): Promise {
+ let current: IHttpResponse;
+
+ return await [...interceptors].reduce(
+ (promise, interceptor) =>
+ promise.then(
+ async httpResponse => {
+ current = httpResponse;
+ checkHalt(controller);
+
+ if (!interceptor.response) {
+ return httpResponse;
+ }
+
+ const interceptorOverrides = (await interceptor.response(httpResponse, controller)) || {};
+
+ return new HttpResponse({
+ ...httpResponse,
+ ...interceptorOverrides,
+ });
+ },
+ async error => {
+ const request = error.request || (current && current.request);
+
+ checkHalt(controller, error);
+
+ if (!interceptor.responseError) {
+ throw error;
+ }
+
+ try {
+ const next = await interceptor.responseError(
+ {
+ error,
+ request,
+ response: error.response || (current && current.response),
+ body: error.body || (current && current.body),
+ },
+ controller
+ );
+
+ checkHalt(controller, error);
+
+ if (!next) {
+ throw error;
+ }
+
+ return new HttpResponse({ ...next, request });
+ } catch (err) {
+ checkHalt(controller, err);
+ throw err;
+ }
+ }
+ ),
+ responsePromise
+ );
+}
+
+function checkHalt(controller: HttpInterceptController, error?: Error) {
+ if (error instanceof HttpInterceptHaltError) {
+ throw error;
+ } else if (controller.halted) {
+ throw new HttpInterceptHaltError();
+ }
+}
diff --git a/src/core/public/http/response.ts b/src/core/public/http/response.ts
new file mode 100644
index 0000000000000..706e7caaca976
--- /dev/null
+++ b/src/core/public/http/response.ts
@@ -0,0 +1,40 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { IHttpResponse } from './types';
+
+export class HttpResponse implements IHttpResponse {
+ public readonly request: Request;
+ public readonly response?: Response;
+ public readonly body?: TResponseBody;
+
+ constructor({
+ request,
+ response,
+ body,
+ }: {
+ request: Request;
+ response?: Response;
+ body?: TResponseBody;
+ }) {
+ this.request = request;
+ this.response = response;
+ this.body = body;
+ }
+}
diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts
index 870d4af8f9e86..48385a72325db 100644
--- a/src/core/public/http/types.ts
+++ b/src/core/public/http/types.ts
@@ -229,31 +229,49 @@ export interface HttpFetchOptions extends HttpRequestInit {
* Headers to send with the request. See {@link HttpHeadersInit}.
*/
headers?: HttpHeadersInit;
+
+ /**
+ * When `true` the return type of {@link HttpHandler} will be an {@link IHttpResponse} with detailed request and
+ * response information. When `false`, the return type will just be the parsed response body. Defaults to `false`.
+ */
+ asResponse?: boolean;
}
/**
* A function for making an HTTP requests to Kibana's backend. See {@link HttpFetchOptions} for options and
- * {@link HttpBody} for the response.
+ * {@link IHttpResponse} for the response.
*
* @param path the path on the Kibana server to send the request to. Should not include the basePath.
* @param options {@link HttpFetchOptions}
- * @returns a Promise that resolves to a {@link HttpBody}
+ * @returns a Promise that resolves to a {@link IHttpResponse}
* @public
*/
-export type HttpHandler = (path: string, options?: HttpFetchOptions) => Promise;
-
-/** @public */
-export type HttpBody = BodyInit | null | any;
+export interface HttpHandler {
+ (path: string, options: HttpFetchOptions & { asResponse: true }): Promise<
+ IHttpResponse
+ >;
+ (path: string, options?: HttpFetchOptions): Promise;
+}
/** @public */
-export interface InterceptedHttpResponse {
- response?: Response;
- body?: HttpBody;
+export interface IHttpResponse {
+ /** Raw request sent to Kibana server. */
+ readonly request: Readonly;
+ /** Raw response received, may be undefined if there was an error. */
+ readonly response?: Readonly;
+ /** Parsed body received, may be undefined if there was an error. */
+ readonly body?: TResponseBody;
}
-/** @public */
-export interface HttpResponse extends InterceptedHttpResponse {
- request: Readonly;
+/**
+ * Properties that can be returned by HttpInterceptor.request to override the response.
+ * @public
+ */
+export interface IHttpResponseInterceptorOverrides {
+ /** Raw response received, may be undefined if there was an error. */
+ readonly response?: Readonly;
+ /** Parsed body received, may be undefined if there was an error. */
+ readonly body?: TResponseBody;
}
/** @public */
@@ -272,7 +290,7 @@ export interface IHttpFetchError extends Error {
}
/** @public */
-export interface HttpErrorResponse extends HttpResponse {
+export interface HttpErrorResponse extends IHttpResponse {
error: Error | IHttpFetchError;
}
/** @public */
@@ -310,13 +328,13 @@ export interface HttpInterceptor {
/**
* Define an interceptor to be executed after a response is received.
- * @param httpResponse {@link HttpResponse}
+ * @param httpResponse {@link IHttpResponse}
* @param controller {@link IHttpInterceptController}
*/
response?(
- httpResponse: HttpResponse,
+ httpResponse: IHttpResponse,
controller: IHttpInterceptController
- ): Promise | InterceptedHttpResponse | void;
+ ): Promise | IHttpResponseInterceptorOverrides | void;
/**
* Define an interceptor to be executed if a response interceptor throws an error or returns a rejected Promise.
@@ -326,7 +344,7 @@ export interface HttpInterceptor {
responseError?(
httpErrorResponse: HttpErrorResponse,
controller: IHttpInterceptController
- ): Promise | InterceptedHttpResponse | void;
+ ): Promise | IHttpResponseInterceptorOverrides | void;
}
/**
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index cfec03427f3e7..035cbcca86ac7 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -112,14 +112,13 @@ export {
HttpErrorResponse,
HttpErrorRequest,
HttpInterceptor,
- HttpResponse,
+ IHttpResponse,
HttpHandler,
- HttpBody,
IBasePath,
IAnonymousPaths,
IHttpInterceptController,
IHttpFetchError,
- InterceptedHttpResponse,
+ IHttpResponseInterceptorOverrides,
} from './http';
export { OverlayStart, OverlayBannersStart, OverlayRef } from './overlays';
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 6fbc7324ce393..157f0bab466b0 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -464,9 +464,6 @@ export type HandlerFunction = (context: T, ...args: any[]) =>
// @public
export type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never;
-// @public (undocumented)
-export type HttpBody = BodyInit | null | any;
-
// @public (undocumented)
export interface HttpErrorRequest {
// (undocumented)
@@ -476,13 +473,14 @@ export interface HttpErrorRequest {
}
// @public (undocumented)
-export interface HttpErrorResponse extends HttpResponse {
+export interface HttpErrorResponse extends IHttpResponse {
// (undocumented)
error: Error | IHttpFetchError;
}
// @public
export interface HttpFetchOptions extends HttpRequestInit {
+ asResponse?: boolean;
headers?: HttpHeadersInit;
prependBasePath?: boolean;
query?: HttpFetchQuery;
@@ -495,7 +493,14 @@ export interface HttpFetchQuery {
}
// @public
-export type HttpHandler = (path: string, options?: HttpFetchOptions) => Promise;
+export interface HttpHandler {
+ // (undocumented)
+ (path: string, options: HttpFetchOptions & {
+ asResponse: true;
+ }): Promise>;
+ // (undocumented)
+ (path: string, options?: HttpFetchOptions): Promise;
+}
// @public (undocumented)
export interface HttpHeadersInit {
@@ -507,8 +512,8 @@ export interface HttpHeadersInit {
export interface HttpInterceptor {
request?(request: Request, controller: IHttpInterceptController): Promise | Request | void;
requestError?(httpErrorRequest: HttpErrorRequest, controller: IHttpInterceptController): Promise | Request | void;
- response?(httpResponse: HttpResponse, controller: IHttpInterceptController): Promise | InterceptedHttpResponse | void;
- responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController): Promise | InterceptedHttpResponse | void;
+ response?(httpResponse: IHttpResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void;
+ responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void;
}
// @public
@@ -529,12 +534,6 @@ export interface HttpRequestInit {
window?: null;
}
-// @public (undocumented)
-export interface HttpResponse extends InterceptedHttpResponse {
- // (undocumented)
- request: Readonly;
-}
-
// @public (undocumented)
export interface HttpServiceBase {
addLoadingCount(countSource$: Observable): void;
@@ -613,11 +612,16 @@ export interface IHttpInterceptController {
}
// @public (undocumented)
-export interface InterceptedHttpResponse {
- // (undocumented)
- body?: HttpBody;
- // (undocumented)
- response?: Response;
+export interface IHttpResponse {
+ readonly body?: TResponseBody;
+ readonly request: Readonly;
+ readonly response?: Readonly;
+}
+
+// @public
+export interface IHttpResponseInterceptorOverrides {
+ readonly body?: TResponseBody;
+ readonly response?: Readonly;
}
// @public
diff --git a/src/plugins/share/public/components/share_context_menu.test.tsx b/src/plugins/share/public/components/share_context_menu.test.tsx
index 7fb0449ead502..1f2242ae4c515 100644
--- a/src/plugins/share/public/components/share_context_menu.test.tsx
+++ b/src/plugins/share/public/components/share_context_menu.test.tsx
@@ -34,7 +34,7 @@ const defaultProps = {
isDirty: false,
onClose: () => {},
basePath: '',
- post: () => Promise.resolve(),
+ post: () => Promise.resolve({} as any),
objectType: 'dashboard',
};
diff --git a/src/plugins/share/public/components/url_panel_content.test.tsx b/src/plugins/share/public/components/url_panel_content.test.tsx
index 9da1a23641ab8..9db8d1ccf2efa 100644
--- a/src/plugins/share/public/components/url_panel_content.test.tsx
+++ b/src/plugins/share/public/components/url_panel_content.test.tsx
@@ -28,7 +28,7 @@ const defaultProps = {
allowShortUrl: true,
objectType: 'dashboard',
basePath: '',
- post: () => Promise.resolve(),
+ post: () => Promise.resolve({} as any),
};
test('render', () => {
diff --git a/x-pack/legacy/plugins/graph/public/services/fetch_top_nodes.test.ts b/x-pack/legacy/plugins/graph/public/services/fetch_top_nodes.test.ts
index 0a0fc8cae5d26..3bfc868fcb06e 100644
--- a/x-pack/legacy/plugins/graph/public/services/fetch_top_nodes.test.ts
+++ b/x-pack/legacy/plugins/graph/public/services/fetch_top_nodes.test.ts
@@ -12,7 +12,7 @@ const icon = getSuitableIcon('');
describe('fetch_top_nodes', () => {
it('should build terms agg', async () => {
const postMock = jest.fn(() => Promise.resolve({ resp: {} }));
- await fetchTopNodes(postMock, 'test', [
+ await fetchTopNodes(postMock as any, 'test', [
{ color: '', hopSize: 5, icon, name: 'field1', selected: false, type: 'string' },
{ color: '', hopSize: 5, icon, name: 'field2', selected: false, type: 'string' },
]);
@@ -64,7 +64,7 @@ describe('fetch_top_nodes', () => {
},
})
);
- const result = await fetchTopNodes(postMock, 'test', [
+ const result = await fetchTopNodes(postMock as any, 'test', [
{ color: 'red', hopSize: 5, icon, name: 'field1', selected: false, type: 'string' },
{ color: 'blue', hopSize: 5, icon, name: 'field2', selected: false, type: 'string' },
]);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
index dc23df250ebd4..52f00a7cd4e9d 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
@@ -278,7 +278,7 @@ describe('IndexPattern Data Panel', () => {
function testProps() {
const setState = jest.fn();
- core.http.get = jest.fn(async (url: string) => {
+ core.http.get.mockImplementation(async (url: string) => {
const parts = url.split('/');
const indexPatternTitle = parts[parts.length - 1];
return {
@@ -484,7 +484,7 @@ describe('IndexPattern Data Panel', () => {
let overlapCount = 0;
const props = testProps();
- core.http.get = jest.fn((url: string) => {
+ core.http.get.mockImplementation((url: string) => {
if (queryCount) {
++overlapCount;
}
@@ -533,11 +533,9 @@ describe('IndexPattern Data Panel', () => {
it('shows all fields if empty state button is clicked', async () => {
const props = testProps();
- core.http.get = jest.fn((url: string) => {
- return Promise.resolve({
- indexPatternTitle: props.currentIndexPatternId,
- existingFieldNames: [],
- });
+ core.http.get.mockResolvedValue({
+ indexPatternTitle: props.currentIndexPatternId,
+ existingFieldNames: [],
});
const inst = mountWithIntl();
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
index 72cbd1b861a05..2fb678aed5a54 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
@@ -528,7 +528,8 @@ describe('loader', () => {
await syncExistingFields({
dateRange: { fromDate: '1900-01-01', toDate: '2000-01-01' },
- fetchJson,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ fetchJson: fetchJson as any,
indexPatterns: [{ title: 'a' }, { title: 'b' }, { title: 'c' }],
setState,
});
diff --git a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts
index 81625e1753b27..8a2251f3f7f7c 100644
--- a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts
+++ b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts
@@ -4,7 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { HttpInterceptor, HttpErrorResponse, HttpResponse, IAnonymousPaths } from 'src/core/public';
+import {
+ HttpInterceptor,
+ HttpErrorResponse,
+ IHttpResponse,
+ IAnonymousPaths,
+} from 'src/core/public';
import { ISessionTimeout } from './session_timeout';
@@ -15,7 +20,7 @@ const isSystemAPIRequest = (request: Request) => {
export class SessionTimeoutHttpInterceptor implements HttpInterceptor {
constructor(private sessionTimeout: ISessionTimeout, private anonymousPaths: IAnonymousPaths) {}
- response(httpResponse: HttpResponse) {
+ response(httpResponse: IHttpResponse) {
if (this.anonymousPaths.isAnonymous(window.location.pathname)) {
return;
}