mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Update KibanaRequest to use the new WHATWG URL API (#80713)
This commit is contained in:
parent
275c30a926
commit
1407f713e5
46 changed files with 262 additions and 113 deletions
|
@ -30,9 +30,9 @@ export declare class KibanaRequest<Params = unknown, Query = unknown, Body = unk
|
|||
| [isSystemRequest](./kibana-plugin-core-server.kibanarequest.issystemrequest.md) | | <code>boolean</code> | Whether or not the request is a "system request" rather than an application-level request. Can be set on the client using the <code>HttpFetchOptions#asSystemRequest</code> option. |
|
||||
| [params](./kibana-plugin-core-server.kibanarequest.params.md) | | <code>Params</code> | |
|
||||
| [query](./kibana-plugin-core-server.kibanarequest.query.md) | | <code>Query</code> | |
|
||||
| [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md) | | <code>Url</code> | URL rewritten in onPreRouting request interceptor. |
|
||||
| [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md) | | <code>URL</code> | URL rewritten in onPreRouting request interceptor. |
|
||||
| [route](./kibana-plugin-core-server.kibanarequest.route.md) | | <code>RecursiveReadonly<KibanaRequestRoute<Method>></code> | matched route details |
|
||||
| [socket](./kibana-plugin-core-server.kibanarequest.socket.md) | | <code>IKibanaSocket</code> | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) |
|
||||
| [url](./kibana-plugin-core-server.kibanarequest.url.md) | | <code>Url</code> | a WHATWG URL standard object. |
|
||||
| [url](./kibana-plugin-core-server.kibanarequest.url.md) | | <code>URL</code> | a WHATWG URL standard object. |
|
||||
| [uuid](./kibana-plugin-core-server.kibanarequest.uuid.md) | | <code>string</code> | A UUID to identify this request. |
|
||||
|
||||
|
|
|
@ -9,5 +9,5 @@ URL rewritten in onPreRouting request interceptor.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
readonly rewrittenUrl?: Url;
|
||||
readonly rewrittenUrl?: URL;
|
||||
```
|
||||
|
|
|
@ -9,5 +9,5 @@ a WHATWG URL standard object.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
readonly url: Url;
|
||||
readonly url: URL;
|
||||
```
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { parse as parseUrl } from 'url';
|
||||
import { Request } from 'hapi';
|
||||
import { merge } from 'lodash';
|
||||
import { Socket } from 'net';
|
||||
|
@ -72,6 +73,7 @@ function createKibanaRequestMock<P = any, Q = any, B = any>({
|
|||
auth = { isAuthenticated: true },
|
||||
}: RequestFixtureOptions<P, Q, B> = {}) {
|
||||
const queryString = stringify(query, { sort: false });
|
||||
const url = parseUrl(`${path}${queryString ? `?${queryString}` : ''}`);
|
||||
|
||||
return KibanaRequest.from<P, Q, B>(
|
||||
createRawRequestMock({
|
||||
|
@ -83,12 +85,7 @@ function createKibanaRequestMock<P = any, Q = any, B = any>({
|
|||
payload: body,
|
||||
path,
|
||||
method,
|
||||
url: {
|
||||
path,
|
||||
pathname: path,
|
||||
query: queryString,
|
||||
search: queryString ? `?${queryString}` : queryString,
|
||||
},
|
||||
url,
|
||||
route: {
|
||||
settings: { tags: routeTags, auth: routeAuthRequired, app: kibanaRouteOptions },
|
||||
},
|
||||
|
@ -121,6 +118,11 @@ interface DeepPartialArray<T> extends Array<DeepPartial<T>> {}
|
|||
type DeepPartialObject<T> = { [P in keyof T]+?: DeepPartial<T[P]> };
|
||||
|
||||
function createRawRequestMock(customization: DeepPartial<Request> = {}) {
|
||||
const pathname = customization.url?.pathname || '/';
|
||||
const path = `${pathname}${customization.url?.search || ''}`;
|
||||
const url = Object.assign({ pathname, path, href: path }, customization.url);
|
||||
|
||||
// @ts-expect-error _core isn't supposed to be accessed - remove once we upgrade to hapi v18
|
||||
return merge(
|
||||
{},
|
||||
{
|
||||
|
@ -129,17 +131,21 @@ function createRawRequestMock(customization: DeepPartial<Request> = {}) {
|
|||
isAuthenticated: true,
|
||||
},
|
||||
headers: {},
|
||||
path: '/',
|
||||
path,
|
||||
route: { settings: {} },
|
||||
url: {
|
||||
href: '/',
|
||||
},
|
||||
url,
|
||||
raw: {
|
||||
req: {
|
||||
url: '/',
|
||||
url: path,
|
||||
socket: {},
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
},
|
||||
customization
|
||||
) as Request;
|
||||
|
|
|
@ -271,7 +271,7 @@ export class HttpServer {
|
|||
}
|
||||
|
||||
this.registerOnPreRouting((request, response, toolkit) => {
|
||||
const oldUrl = request.url.href!;
|
||||
const oldUrl = request.url.pathname + request.url.search;
|
||||
const newURL = basePathService.remove(oldUrl);
|
||||
const shouldRedirect = newURL !== oldUrl;
|
||||
if (shouldRedirect) {
|
||||
|
|
|
@ -124,7 +124,13 @@ describe('OnPreRouting', () => {
|
|||
const router = createRouter('/');
|
||||
|
||||
router.get({ path: '/login', validate: false }, (context, req, res) => {
|
||||
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
|
||||
return res.ok({
|
||||
body: {
|
||||
rewrittenUrl: req.rewrittenUrl
|
||||
? `${req.rewrittenUrl.pathname}${req.rewrittenUrl.search}`
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
registerOnPreRouting((req, res, t) => t.rewriteUrl('/login'));
|
||||
|
@ -143,7 +149,13 @@ describe('OnPreRouting', () => {
|
|||
const router = createRouter('/');
|
||||
|
||||
router.get({ path: '/reroute-2', validate: false }, (context, req, res) => {
|
||||
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
|
||||
return res.ok({
|
||||
body: {
|
||||
rewrittenUrl: req.rewrittenUrl
|
||||
? `${req.rewrittenUrl.pathname}${req.rewrittenUrl.search}`
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
registerOnPreRouting((req, res, t) => t.rewriteUrl('/reroute-1'));
|
||||
|
@ -163,7 +175,13 @@ describe('OnPreRouting', () => {
|
|||
const router = createRouter('/');
|
||||
|
||||
router.get({ path: '/login', validate: false }, (context, req, res) => {
|
||||
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
|
||||
return res.ok({
|
||||
body: {
|
||||
rewrittenUrl: req.rewrittenUrl
|
||||
? `${req.rewrittenUrl.pathname}${req.rewrittenUrl.search}`
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
registerOnPreRouting((req, res, t) => t.next());
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { URL } from 'url';
|
||||
import { Lifecycle, Request, ResponseToolkit as HapiResponseToolkit } from 'hapi';
|
||||
import { Logger } from '../../logging';
|
||||
import {
|
||||
|
@ -110,10 +111,30 @@ export function adoptToHapiOnRequest(fn: OnPreRoutingHandler, log: Logger) {
|
|||
|
||||
if (preRoutingResult.isRewriteUrl(result)) {
|
||||
const appState = request.app as KibanaRequestState;
|
||||
appState.rewrittenUrl = appState.rewrittenUrl ?? request.url;
|
||||
appState.rewrittenUrl =
|
||||
// @ts-expect-error request._core isn't supposed to be accessed - remove once we upgrade to hapi v18
|
||||
appState.rewrittenUrl ?? new URL(request.url.href!, request._core.info.uri);
|
||||
|
||||
const { url } = result;
|
||||
request.setUrl(url);
|
||||
|
||||
// TODO: Remove once we upgrade to Node.js 12!
|
||||
//
|
||||
// Warning: The following for-loop took 10 days to write, and is a hack
|
||||
// to force V8 to make a copy of the string in memory.
|
||||
//
|
||||
// The reason why we need this is because of what appears to be a bug
|
||||
// in V8 that caused some URL paths to not be routed correctly once
|
||||
// `request.setUrl` was called with the path.
|
||||
//
|
||||
// The details can be seen in this discussion on Twitter:
|
||||
// https://twitter.com/wa7son/status/1319992632366518277
|
||||
let urlCopy = '';
|
||||
for (let i = 0; i < url.length; i++) {
|
||||
urlCopy += url[i];
|
||||
}
|
||||
|
||||
request.setUrl(urlCopy);
|
||||
|
||||
// We should update raw request as well since it can be proxied to the old platform
|
||||
request.raw.req.url = url;
|
||||
return responseToolkit.continue;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Url } from 'url';
|
||||
import { URL } from 'url';
|
||||
import uuid from 'uuid';
|
||||
import { Request, RouteOptionsApp, ApplicationState } from 'hapi';
|
||||
import { Observable, fromEvent, merge } from 'rxjs';
|
||||
|
@ -45,7 +45,7 @@ export interface KibanaRouteOptions extends RouteOptionsApp {
|
|||
export interface KibanaRequestState extends ApplicationState {
|
||||
requestId: string;
|
||||
requestUuid: string;
|
||||
rewrittenUrl?: Url;
|
||||
rewrittenUrl?: URL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,7 +163,7 @@ export class KibanaRequest<
|
|||
*/
|
||||
public readonly uuid: string;
|
||||
/** a WHATWG URL standard object. */
|
||||
public readonly url: Url;
|
||||
public readonly url: URL;
|
||||
/** matched route details */
|
||||
public readonly route: RecursiveReadonly<KibanaRequestRoute<Method>>;
|
||||
/**
|
||||
|
@ -190,7 +190,7 @@ export class KibanaRequest<
|
|||
/**
|
||||
* URL rewritten in onPreRouting request interceptor.
|
||||
*/
|
||||
public readonly rewrittenUrl?: Url;
|
||||
public readonly rewrittenUrl?: URL;
|
||||
|
||||
/** @internal */
|
||||
protected readonly [requestSymbol]: Request;
|
||||
|
@ -212,7 +212,8 @@ export class KibanaRequest<
|
|||
this.uuid = appState?.requestUuid ?? uuid.v4();
|
||||
this.rewrittenUrl = appState?.rewrittenUrl;
|
||||
|
||||
this.url = request.url;
|
||||
// @ts-expect-error request._core isn't supposed to be accessed - remove once we upgrade to hapi v18
|
||||
this.url = new URL(request.url.href!, request._core.info.uri);
|
||||
this.headers = deepFreeze({ ...request.headers });
|
||||
this.isSystemRequest =
|
||||
request.headers['kbn-system-request'] === 'true' ||
|
||||
|
@ -304,8 +305,8 @@ export class KibanaRequest<
|
|||
if (authOptions === false) return false;
|
||||
throw new Error(
|
||||
`unexpected authentication options: ${JSON.stringify(authOptions)} for route: ${
|
||||
this.url.href
|
||||
}`
|
||||
this.url.pathname
|
||||
}${this.url.search}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ import { Type } from '@kbn/config-schema';
|
|||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { UpdateDocumentByQueryParams } from 'elasticsearch';
|
||||
import { UpdateDocumentParams } from 'elasticsearch';
|
||||
import { Url } from 'url';
|
||||
import { URL } from 'url';
|
||||
|
||||
// @public
|
||||
export interface AppCategory {
|
||||
|
@ -1007,11 +1007,11 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown, Me
|
|||
readonly params: Params;
|
||||
// (undocumented)
|
||||
readonly query: Query;
|
||||
readonly rewrittenUrl?: Url;
|
||||
readonly rewrittenUrl?: URL;
|
||||
readonly route: RecursiveReadonly<KibanaRequestRoute<Method>>;
|
||||
// (undocumented)
|
||||
readonly socket: IKibanaSocket;
|
||||
readonly url: Url;
|
||||
readonly url: URL;
|
||||
readonly uuid: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,12 @@ test('executes the task by calling the executor with proper parameters', async (
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -271,6 +277,12 @@ test('uses API key when provided', async () => {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -310,6 +322,12 @@ test(`doesn't use API key when not provided`, async () => {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -102,6 +102,12 @@ export class TaskRunnerFactory {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
let executorResult: ActionTypeExecutorResult<unknown>;
|
||||
|
|
|
@ -60,6 +60,12 @@ const fakeRequest = ({
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
getSavedObjectsClient: () => savedObjectsClient,
|
||||
} as unknown) as Request;
|
||||
|
||||
|
|
|
@ -149,6 +149,12 @@ describe('Alerting Plugin', () => {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
getSavedObjectsClient: jest.fn(),
|
||||
} as unknown) as KibanaRequest;
|
||||
await startContract.getAlertsClientWithRequest(fakeRequest);
|
||||
|
|
|
@ -364,6 +364,12 @@ describe('Task Runner', () => {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
|
||||
expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
|
@ -662,6 +668,12 @@ describe('Task Runner', () => {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -694,6 +706,12 @@ describe('Task Runner', () => {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -101,6 +101,12 @@ export class TaskRunner {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { parse as parseUrl } from 'url';
|
||||
import {
|
||||
OnPostAuthHandler,
|
||||
OnPostAuthToolkit,
|
||||
|
@ -45,7 +46,7 @@ describe('DashboardOnlyModeRequestInterceptor', () => {
|
|||
test('should not redirects for not app/* requests', async () => {
|
||||
const request = ({
|
||||
url: {
|
||||
path: 'api/test',
|
||||
pathname: 'api/test',
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
|
@ -57,7 +58,7 @@ describe('DashboardOnlyModeRequestInterceptor', () => {
|
|||
test('should not redirects not authenticated users', async () => {
|
||||
const request = ({
|
||||
url: {
|
||||
path: '/app/home',
|
||||
pathname: '/app/home',
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
|
@ -70,10 +71,9 @@ describe('DashboardOnlyModeRequestInterceptor', () => {
|
|||
function testRedirectToDashboardModeApp(url: string) {
|
||||
describe(`requests to url:"${url}"`, () => {
|
||||
test('redirects to the dashboard_mode app instead', async () => {
|
||||
const { pathname, search, hash } = parseUrl(url);
|
||||
const request = ({
|
||||
url: {
|
||||
path: url,
|
||||
},
|
||||
url: { pathname, search, hash },
|
||||
credentials: {
|
||||
roles: [DASHBOARD_ONLY_MODE_ROLE],
|
||||
},
|
||||
|
|
|
@ -22,7 +22,7 @@ export const setupDashboardModeRequestInterceptor = ({
|
|||
getUiSettingsClient,
|
||||
}: DashboardModeRequestInterceptorDependencies) =>
|
||||
(async (request, response, toolkit) => {
|
||||
const path = request.url.path || '';
|
||||
const path = request.url.pathname;
|
||||
const isAppRequest = path.startsWith('/app/');
|
||||
|
||||
if (!isAppRequest) {
|
||||
|
|
|
@ -21,7 +21,6 @@ describe('callEnterpriseSearchConfigAPI', () => {
|
|||
accessCheckTimeoutWarning: 100,
|
||||
};
|
||||
const mockRequest = {
|
||||
url: { path: '/app/kibana' },
|
||||
headers: { authorization: '==someAuth' },
|
||||
};
|
||||
const mockDependencies = {
|
||||
|
|
|
@ -322,6 +322,12 @@ function FakeRequest(): KibanaRequest {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
getSavedObjectsClient: () => savedObjectGetter,
|
||||
} as unknown) as KibanaRequest;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@ function fakeRequest(): KibanaRequest {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
getSavedObjectsClient: () => savedObjectsClient,
|
||||
} as unknown) as KibanaRequest;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,12 @@ function fakeRequest(): KibanaRequest {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
getSavedObjectsClient: () => savedObjectsClient,
|
||||
} as unknown) as KibanaRequest;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,12 @@ const fakeRequest = ({
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
export async function agentPolicyUpdateEventHandler(
|
||||
|
|
|
@ -23,6 +23,12 @@ function getInternalUserSOClient() {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
return appContextService.getInternalUserSOClient(fakeRequest);
|
||||
|
|
|
@ -58,6 +58,12 @@ function getInternalUserSOClient() {
|
|||
url: '/',
|
||||
},
|
||||
},
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
return appContextService.getInternalUserSOClient(fakeRequest);
|
||||
|
|
|
@ -456,16 +456,10 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat
|
|||
},
|
||||
mlLicense.fullLicenseAPIGuard(async ({ client, request, response }) => {
|
||||
try {
|
||||
const options: { id: string; force?: boolean | undefined } = {
|
||||
const { body } = await client.asInternalUser.ml.stopDataFrameAnalytics({
|
||||
id: request.params.analyticsId,
|
||||
};
|
||||
// @ts-expect-error TODO: update types
|
||||
if (request.url?.query?.force !== undefined) {
|
||||
// @ts-expect-error TODO: update types
|
||||
options.force = request.url.query.force;
|
||||
}
|
||||
|
||||
const { body } = await client.asInternalUser.ml.stopDataFrameAnalytics(options);
|
||||
force: request.query.force,
|
||||
});
|
||||
return response.ok({
|
||||
body,
|
||||
});
|
||||
|
|
|
@ -210,11 +210,18 @@ export class ReportingCore {
|
|||
}
|
||||
|
||||
public getFakeRequest(baseRequest: object, spaceId: string | undefined, logger = this.logger) {
|
||||
// @ts-expect-error _core isn't supposed to be accessed - remove once we upgrade to hapi v18
|
||||
const fakeRequest = KibanaRequest.from({
|
||||
path: '/',
|
||||
route: { settings: {} },
|
||||
url: { href: '/' },
|
||||
raw: { req: { url: '/' } },
|
||||
// TODO: Remove once we upgrade to hapi v18
|
||||
_core: {
|
||||
info: {
|
||||
uri: 'http://localhost',
|
||||
},
|
||||
},
|
||||
...baseRequest,
|
||||
} as Hapi.Request);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ const getMockContext = () =>
|
|||
|
||||
const getMockRequest = () =>
|
||||
({
|
||||
url: { port: '5601', query: '', path: '/foo' },
|
||||
url: { port: '5601', search: '', pathname: '/foo' },
|
||||
route: { path: '/foo', options: {} },
|
||||
} as KibanaRequest);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { URL } from 'url';
|
||||
import {
|
||||
EventOutcome,
|
||||
SavedObjectAction,
|
||||
|
@ -192,11 +193,11 @@ describe('#httpRequestEvent', () => {
|
|||
},
|
||||
"message": "User is requesting [/path] endpoint",
|
||||
"url": Object {
|
||||
"domain": undefined,
|
||||
"domain": "localhost",
|
||||
"path": "/path",
|
||||
"port": undefined,
|
||||
"query": undefined,
|
||||
"scheme": undefined,
|
||||
"scheme": "http:",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
@ -211,12 +212,7 @@ describe('#httpRequestEvent', () => {
|
|||
kibanaRequestState: {
|
||||
requestId: '123',
|
||||
requestUuid: '123e4567-e89b-12d3-a456-426614174000',
|
||||
rewrittenUrl: {
|
||||
path: '/original/path',
|
||||
pathname: '/original/path',
|
||||
query: 'query=param',
|
||||
search: '?query=param',
|
||||
},
|
||||
rewrittenUrl: new URL('http://localhost/original/path?query=param'),
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
@ -234,11 +230,11 @@ describe('#httpRequestEvent', () => {
|
|||
},
|
||||
"message": "User is requesting [/original/path] endpoint",
|
||||
"url": Object {
|
||||
"domain": undefined,
|
||||
"domain": "localhost",
|
||||
"path": "/original/path",
|
||||
"port": undefined,
|
||||
"query": "query=param",
|
||||
"scheme": undefined,
|
||||
"scheme": "http:",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
|
|
@ -105,10 +105,10 @@ export interface HttpRequestParams {
|
|||
}
|
||||
|
||||
export function httpRequestEvent({ request }: HttpRequestParams): AuditEvent {
|
||||
const { pathname, search } = request.rewrittenUrl ?? request.url;
|
||||
const url = request.rewrittenUrl ?? request.url;
|
||||
|
||||
return {
|
||||
message: `User is requesting [${pathname}] endpoint`,
|
||||
message: `User is requesting [${url.pathname}] endpoint`,
|
||||
event: {
|
||||
action: 'http_request',
|
||||
category: EventCategory.WEB,
|
||||
|
@ -120,11 +120,11 @@ export function httpRequestEvent({ request }: HttpRequestParams): AuditEvent {
|
|||
},
|
||||
},
|
||||
url: {
|
||||
domain: request.url.hostname,
|
||||
path: pathname,
|
||||
port: request.url.port ? parseInt(request.url.port, 10) : undefined,
|
||||
query: search?.slice(1) || undefined,
|
||||
scheme: request.url.protocol,
|
||||
domain: url.hostname,
|
||||
path: url.pathname,
|
||||
port: url.port ? parseInt(url.port, 10) : undefined,
|
||||
query: url.search ? url.search.slice(1) : undefined,
|
||||
scheme: url.protocol,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -333,7 +333,7 @@ export class Authenticator {
|
|||
this.logger.debug('Redirecting request to Login Selector.');
|
||||
return AuthenticationResult.redirectTo(
|
||||
`${this.options.basePath.serverBasePath}/login?next=${encodeURIComponent(
|
||||
`${this.options.basePath.get(request)}${request.url.path}`
|
||||
`${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}`
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
@ -728,7 +728,7 @@ export class Authenticator {
|
|||
preAccessRedirectURL = `${preAccessRedirectURL}?next=${encodeURIComponent(
|
||||
authenticationResult.redirectURL ||
|
||||
redirectURL ||
|
||||
`${this.options.basePath.get(request)}${request.url.path}`
|
||||
`${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}`
|
||||
)}`;
|
||||
} else if (redirectURL && !authenticationResult.redirectURL) {
|
||||
preAccessRedirectURL = redirectURL;
|
||||
|
|
|
@ -101,13 +101,13 @@ describe('BasicAuthenticationProvider', () => {
|
|||
await expect(
|
||||
provider.authenticate(
|
||||
httpServerMock.createKibanaRequest({
|
||||
path: '/s/foo/some-path # that needs to be encoded',
|
||||
path: '/s/foo/some path that needs to be encoded',
|
||||
}),
|
||||
null
|
||||
)
|
||||
).resolves.toEqual(
|
||||
AuthenticationResult.redirectTo(
|
||||
'/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded'
|
||||
'/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome%2520path%2520that%2520needs%2520to%2520be%2520encoded'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -90,7 +90,9 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}.`
|
||||
);
|
||||
|
||||
if (HTTPAuthorizationHeader.parseFromRequest(request) != null) {
|
||||
this.logger.debug('Cannot authenticate requests with `Authorization` header.');
|
||||
|
@ -106,7 +108,9 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
this.logger.debug('Redirecting request to Login page.');
|
||||
const basePath = this.options.basePath.get(request);
|
||||
return AuthenticationResult.redirectTo(
|
||||
`${basePath}/login?next=${encodeURIComponent(`${basePath}${request.url.path}`)}`
|
||||
`${basePath}/login?next=${encodeURIComponent(
|
||||
`${basePath}${request.url.pathname}${request.url.search}`
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -119,7 +123,7 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async logout(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to log user out via ${request.url.path}.`);
|
||||
this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`);
|
||||
|
||||
// Having a `null` state means that provider was specifically called to do a logout, but when
|
||||
// session isn't defined then provider is just being probed whether or not it can perform logout.
|
||||
|
|
|
@ -56,7 +56,9 @@ export class HTTPAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param request Request instance.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}.`
|
||||
);
|
||||
|
||||
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request);
|
||||
if (authorizationHeader == null) {
|
||||
|
@ -72,12 +74,12 @@ export class HTTPAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
try {
|
||||
const user = await this.getUser(request);
|
||||
this.logger.debug(
|
||||
`Request to ${request.url.path} has been authenticated via authorization header with "${authorizationHeader.scheme}" scheme.`
|
||||
`Request to ${request.url.pathname}${request.url.search} has been authenticated via authorization header with "${authorizationHeader.scheme}" scheme.`
|
||||
);
|
||||
return AuthenticationResult.succeeded(user);
|
||||
} catch (err) {
|
||||
this.logger.debug(
|
||||
`Failed to authenticate request to ${request.url.path} via authorization header with "${authorizationHeader.scheme}" scheme: ${err.message}`
|
||||
`Failed to authenticate request to ${request.url.pathname}${request.url.search} via authorization header with "${authorizationHeader.scheme}" scheme: ${err.message}`
|
||||
);
|
||||
return AuthenticationResult.failed(err);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,9 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}.`
|
||||
);
|
||||
|
||||
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request);
|
||||
if (authorizationHeader && authorizationHeader.scheme.toLowerCase() !== 'negotiate') {
|
||||
|
@ -100,7 +102,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param state State value previously stored by the provider.
|
||||
*/
|
||||
public async logout(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to log user out via ${request.url.path}.`);
|
||||
this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`);
|
||||
|
||||
// Having a `null` state means that provider was specifically called to do a logout, but when
|
||||
// session isn't defined then provider is just being probed whether or not it can perform logout.
|
||||
|
|
|
@ -166,7 +166,9 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}.`
|
||||
);
|
||||
|
||||
if (HTTPAuthorizationHeader.parseFromRequest(request) != null) {
|
||||
this.logger.debug('Cannot authenticate requests with `Authorization` header.');
|
||||
|
@ -418,7 +420,7 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param state State value previously stored by the provider.
|
||||
*/
|
||||
public async logout(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to log user out via ${request.url.path}.`);
|
||||
this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`);
|
||||
|
||||
// Having a `null` state means that provider was specifically called to do a logout, but when
|
||||
// session isn't defined then provider is just being probed whether or not it can perform logout.
|
||||
|
@ -477,7 +479,7 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
`${
|
||||
this.options.basePath.serverBasePath
|
||||
}/internal/security/capture-url?next=${encodeURIComponent(
|
||||
`${this.options.basePath.get(request)}${request.url.path}`
|
||||
`${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}`
|
||||
)}&providerType=${encodeURIComponent(this.type)}&providerName=${encodeURIComponent(
|
||||
this.options.name
|
||||
)}`,
|
||||
|
|
|
@ -61,7 +61,9 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}.`
|
||||
);
|
||||
|
||||
if (HTTPAuthorizationHeader.parseFromRequest(request) != null) {
|
||||
this.logger.debug('Cannot authenticate requests with `Authorization` header.');
|
||||
|
@ -105,7 +107,7 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param state State value previously stored by the provider.
|
||||
*/
|
||||
public async logout(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to log user out via ${request.url.path}.`);
|
||||
this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`);
|
||||
|
||||
// Having a `null` state means that provider was specifically called to do a logout, but when
|
||||
// session isn't defined then provider is just being probed whether or not it can perform logout.
|
||||
|
|
|
@ -193,7 +193,9 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}`
|
||||
);
|
||||
|
||||
if (HTTPAuthorizationHeader.parseFromRequest(request) != null) {
|
||||
this.logger.debug('Cannot authenticate requests with `Authorization` header.');
|
||||
|
@ -232,7 +234,7 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param state State value previously stored by the provider.
|
||||
*/
|
||||
public async logout(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to log user out via ${request.url.path}.`);
|
||||
this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`);
|
||||
|
||||
// Normally when there is no active session in Kibana, `logout` method shouldn't do anything
|
||||
// and user will eventually be redirected to the home page to log in. But when SAML SLO is
|
||||
|
@ -631,7 +633,7 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
`${
|
||||
this.options.basePath.serverBasePath
|
||||
}/internal/security/capture-url?next=${encodeURIComponent(
|
||||
`${this.options.basePath.get(request)}${request.url.path}`
|
||||
`${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}`
|
||||
)}&providerType=${encodeURIComponent(this.type)}&providerName=${encodeURIComponent(
|
||||
this.options.name
|
||||
)}`,
|
||||
|
|
|
@ -173,13 +173,13 @@ describe('TokenAuthenticationProvider', () => {
|
|||
await expect(
|
||||
provider.authenticate(
|
||||
httpServerMock.createKibanaRequest({
|
||||
path: '/s/foo/some-path # that needs to be encoded',
|
||||
path: '/s/foo/some path that needs to be encoded',
|
||||
}),
|
||||
null
|
||||
)
|
||||
).resolves.toEqual(
|
||||
AuthenticationResult.redirectTo(
|
||||
'/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded'
|
||||
'/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome%2520path%2520that%2520needs%2520to%2520be%2520encoded'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -92,7 +92,9 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param [state] Optional state object associated with the provider.
|
||||
*/
|
||||
public async authenticate(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`);
|
||||
this.logger.debug(
|
||||
`Trying to authenticate user request to ${request.url.pathname}${request.url.search}.`
|
||||
);
|
||||
|
||||
if (HTTPAuthorizationHeader.parseFromRequest(request) != null) {
|
||||
this.logger.debug('Cannot authenticate requests with `Authorization` header.');
|
||||
|
@ -126,7 +128,7 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param state State value previously stored by the provider.
|
||||
*/
|
||||
public async logout(request: KibanaRequest, state?: ProviderState | null) {
|
||||
this.logger.debug(`Trying to log user out via ${request.url.path}.`);
|
||||
this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`);
|
||||
|
||||
// Having a `null` state means that provider was specifically called to do a logout, but when
|
||||
// session isn't defined then provider is just being probed whether or not it can perform logout.
|
||||
|
@ -241,7 +243,9 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider {
|
|||
* @param request Request instance.
|
||||
*/
|
||||
private getLoginPageURL(request: KibanaRequest) {
|
||||
const nextURL = encodeURIComponent(`${this.options.basePath.get(request)}${request.url.path}`);
|
||||
const nextURL = encodeURIComponent(
|
||||
`${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}`
|
||||
);
|
||||
return `${this.options.basePath.get(request)}/login?next=${nextURL}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,11 +33,13 @@ export function initAPIAuthorization(
|
|||
|
||||
// we've actually authorized the request
|
||||
if (checkPrivilegesResponse.hasAllRequested) {
|
||||
logger.debug(`User authorized for "${request.url.path}"`);
|
||||
logger.debug(`User authorized for "${request.url.pathname}${request.url.search}"`);
|
||||
return toolkit.next();
|
||||
}
|
||||
|
||||
logger.warn(`User not authorized for "${request.url.path}": responding with 403`);
|
||||
logger.warn(
|
||||
`User not authorized for "${request.url.pathname}${request.url.search}": responding with 403`
|
||||
);
|
||||
return response.forbidden();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ export class AuthorizationService {
|
|||
http.registerOnPreResponse((request, preResponse, toolkit) => {
|
||||
if (preResponse.statusCode === 403 && canRedirectRequest(request)) {
|
||||
const basePath = http.basePath.get(request);
|
||||
const next = `${basePath}${request.url.path}`;
|
||||
const next = `${basePath}${request.url.pathname}${request.url.search}`;
|
||||
const regularBundlePath = `${basePath}/${buildNumber}/bundles`;
|
||||
|
||||
const logoutUrl = http.basePath.prepend(
|
||||
|
|
|
@ -135,7 +135,7 @@ export function defineOIDCRoutes({
|
|||
loginAttempt = {
|
||||
type: OIDCLogin.LoginWithAuthorizationCodeFlow,
|
||||
// We pass the path only as we can't be sure of the full URL and Elasticsearch doesn't need it anyway.
|
||||
authenticationResponseURI: request.url.path!,
|
||||
authenticationResponseURI: request.url.pathname + request.url.search,
|
||||
};
|
||||
} else if (request.query.iss) {
|
||||
logger.warn(
|
||||
|
|
|
@ -100,7 +100,7 @@ describe('Login view routes', () => {
|
|||
auth: { isAuthenticated: true },
|
||||
});
|
||||
(request as any).url = new URL(
|
||||
`${request.url.path}${request.url.search}`,
|
||||
`${request.url.pathname}${request.url.search}`,
|
||||
'https://kibana.co'
|
||||
);
|
||||
license.getFeatures.mockReturnValue({ showLogin: true } as any);
|
||||
|
@ -114,7 +114,7 @@ describe('Login view routes', () => {
|
|||
// Redirect if `showLogin` is `false` even if user is not authenticated.
|
||||
request = httpServerMock.createKibanaRequest({ query, auth: { isAuthenticated: false } });
|
||||
(request as any).url = new URL(
|
||||
`${request.url.path}${request.url.search}`,
|
||||
`${request.url.pathname}${request.url.search}`,
|
||||
'https://kibana.co'
|
||||
);
|
||||
license.getFeatures.mockReturnValue({ showLogin: false } as any);
|
||||
|
|
|
@ -28,7 +28,7 @@ export function initSpacesOnPostAuthRequestInterceptor({
|
|||
http.registerOnPostAuth(async (request, response, toolkit) => {
|
||||
const serverBasePath = http.basePath.serverBasePath;
|
||||
|
||||
const path = request.url.pathname!;
|
||||
const path = request.url.pathname;
|
||||
|
||||
const spaceId = spacesService.getSpaceId(request);
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import {
|
|||
LifecycleResponseFactory,
|
||||
CoreSetup,
|
||||
} from 'src/core/server';
|
||||
import { format } from 'url';
|
||||
import { modifyUrl } from '../utils/url';
|
||||
import { getSpaceIdFromPath } from '../../../common';
|
||||
|
||||
export interface OnRequestInterceptorDeps {
|
||||
|
@ -34,16 +32,9 @@ export function initSpacesOnRequestInterceptor({ http }: OnRequestInterceptorDep
|
|||
|
||||
http.basePath.set(request, reqBasePath);
|
||||
|
||||
const newLocation = (path && path.substr(reqBasePath.length)) || '/';
|
||||
const newPathname = path.substr(reqBasePath.length) || '/';
|
||||
|
||||
const newUrl = modifyUrl(format(request.url), (parts) => {
|
||||
return {
|
||||
...parts,
|
||||
pathname: newLocation,
|
||||
};
|
||||
});
|
||||
|
||||
return toolkit.rewriteUrl(newUrl);
|
||||
return toolkit.rewriteUrl(`${newPathname}${request.url.search}`);
|
||||
}
|
||||
|
||||
return toolkit.next();
|
||||
|
|
|
@ -58,7 +58,7 @@ const createService = async (serverBasePath: string = '') => {
|
|||
serverBasePath,
|
||||
} as HttpServiceSetup['basePath'];
|
||||
httpSetup.basePath.get = jest.fn().mockImplementation((request: KibanaRequest) => {
|
||||
const { spaceId } = getSpaceIdFromPath(request.url.path);
|
||||
const { spaceId } = getSpaceIdFromPath(request.url.pathname);
|
||||
|
||||
if (spaceId !== DEFAULT_SPACE_ID) {
|
||||
return `/s/${spaceId}`;
|
||||
|
@ -83,7 +83,7 @@ describe('SpacesService', () => {
|
|||
const spacesServiceSetup = await createService();
|
||||
|
||||
const request: KibanaRequest = {
|
||||
url: { path: '/app/kibana' },
|
||||
url: { pathname: '/app/kibana' },
|
||||
} as KibanaRequest;
|
||||
|
||||
expect(spacesServiceSetup.getSpaceId(request)).toEqual(DEFAULT_SPACE_ID);
|
||||
|
@ -93,7 +93,7 @@ describe('SpacesService', () => {
|
|||
const spacesServiceSetup = await createService();
|
||||
|
||||
const request: KibanaRequest = {
|
||||
url: { path: '/s/foo/app/kibana' },
|
||||
url: { pathname: '/s/foo/app/kibana' },
|
||||
} as KibanaRequest;
|
||||
|
||||
expect(spacesServiceSetup.getSpaceId(request)).toEqual('foo');
|
||||
|
@ -140,7 +140,7 @@ describe('SpacesService', () => {
|
|||
const spacesServiceSetup = await createService();
|
||||
|
||||
const request: KibanaRequest = {
|
||||
url: { path: '/app/kibana' },
|
||||
url: { pathname: '/app/kibana' },
|
||||
} as KibanaRequest;
|
||||
|
||||
expect(spacesServiceSetup.isInDefaultSpace(request)).toEqual(true);
|
||||
|
@ -150,7 +150,7 @@ describe('SpacesService', () => {
|
|||
const spacesServiceSetup = await createService();
|
||||
|
||||
const request: KibanaRequest = {
|
||||
url: { path: '/s/foo/app/kibana' },
|
||||
url: { pathname: '/s/foo/app/kibana' },
|
||||
} as KibanaRequest;
|
||||
|
||||
expect(spacesServiceSetup.isInDefaultSpace(request)).toEqual(false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue