mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.12`: - [[HTTP] Allow default resolution to be used for certain internal routes (#175029)](https://github.com/elastic/kibana/pull/175029) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Jean-Louis Leysens","email":"jeanlouis.leysens@elastic.co"},"sourceCommit":{"committedDate":"2024-01-23T08:36:53Z","message":"[HTTP] Allow default resolution to be used for certain internal routes (#175029)\n\n## Summary\r\n\r\nWhen we rolled out the ability to create versioned routes the version\r\nparameters for internal routes became mandatory. However, there are\r\nseveral past instances where users integrating with Kibana come to rely\r\non routes intended for internal access only, and developers may not be\r\naware of this reliance.\r\n\r\nIn very select cases where passing version params (via headers) is not\r\npossible or cumbersome it would be useful to lift the breaking change\r\nrather than force users to, for example, abandon an upgrade.\r\n\r\nThus, this piece of advanced user config\r\n`useDefaultResolutionStrategyForInternalPaths` is added to enable the\r\ndefault version resolution to be used on select internal paths. Use\r\nlike:\r\n\r\n```yaml\r\nserver.versioned.useVersionResolutionStrategyForInternalPaths: ['/cool_path/{id?}']\r\n```\r\n\r\n\r\n## How to test\r\n\r\n* Start Kibana with the following in `kibana.dev.yml`\r\n\r\n```yaml\r\nserver.versioned:\r\n useVersionResolutionStrategyForInternalPaths: ['/internal/fleet/reset_preconfigured_agent_policies']\r\n versionResolution: 'oldest'\r\n```\r\n\r\n* Run this cURL command (assuming no base path mode)\r\n\r\n```sh\r\ncurl -uelastic:changeme http://localhost:5601/internal/fleet/reset_preconfigured_agent_policies -H 'content-type: application/json' -H 'kbn-xsrf: true' -d '{}'\r\n```\r\n\r\n* Your request should receive `200`\r\n\r\nDo the same but removing `useDefaultResolutionStrategyForInternalPaths`\r\nshould result in `400` with an error about version parameter missing.\r\n\r\n## Risks\r\n<!--\r\nProvide a matrix or statement of known risks and how they are mitigated.\r\nSee risk examples:\r\nhttps://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx\r\n-->\r\n\r\n* Configuration is not used as intended or is relied upon by users. The\r\nlikelihood is **low** but severity **high**. To mitigate this, the\r\nconfiguration is designed to be cumbersome and, likely, to break over\r\ntime as internal paths evolve. Additionally the configuration is\r\ndisabled for serverless.\r\n\r\n\r\n## Notes\r\n\r\n* Added schema that will forbid this setting in serverless environments\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"615c16ec8a692ea8125811141045504ff40157fe","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:http","Team:Core","release_note:skip","v8.12.0","v8.12.1","v8.13.0","v8.11.4","v8.11.5"],"title":"[HTTP] Allow default resolution to be used for certain internal routes","number":175029,"url":"https://github.com/elastic/kibana/pull/175029","mergeCommit":{"message":"[HTTP] Allow default resolution to be used for certain internal routes (#175029)\n\n## Summary\r\n\r\nWhen we rolled out the ability to create versioned routes the version\r\nparameters for internal routes became mandatory. However, there are\r\nseveral past instances where users integrating with Kibana come to rely\r\non routes intended for internal access only, and developers may not be\r\naware of this reliance.\r\n\r\nIn very select cases where passing version params (via headers) is not\r\npossible or cumbersome it would be useful to lift the breaking change\r\nrather than force users to, for example, abandon an upgrade.\r\n\r\nThus, this piece of advanced user config\r\n`useDefaultResolutionStrategyForInternalPaths` is added to enable the\r\ndefault version resolution to be used on select internal paths. Use\r\nlike:\r\n\r\n```yaml\r\nserver.versioned.useVersionResolutionStrategyForInternalPaths: ['/cool_path/{id?}']\r\n```\r\n\r\n\r\n## How to test\r\n\r\n* Start Kibana with the following in `kibana.dev.yml`\r\n\r\n```yaml\r\nserver.versioned:\r\n useVersionResolutionStrategyForInternalPaths: ['/internal/fleet/reset_preconfigured_agent_policies']\r\n versionResolution: 'oldest'\r\n```\r\n\r\n* Run this cURL command (assuming no base path mode)\r\n\r\n```sh\r\ncurl -uelastic:changeme http://localhost:5601/internal/fleet/reset_preconfigured_agent_policies -H 'content-type: application/json' -H 'kbn-xsrf: true' -d '{}'\r\n```\r\n\r\n* Your request should receive `200`\r\n\r\nDo the same but removing `useDefaultResolutionStrategyForInternalPaths`\r\nshould result in `400` with an error about version parameter missing.\r\n\r\n## Risks\r\n<!--\r\nProvide a matrix or statement of known risks and how they are mitigated.\r\nSee risk examples:\r\nhttps://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx\r\n-->\r\n\r\n* Configuration is not used as intended or is relied upon by users. The\r\nlikelihood is **low** but severity **high**. To mitigate this, the\r\nconfiguration is designed to be cumbersome and, likely, to break over\r\ntime as internal paths evolve. Additionally the configuration is\r\ndisabled for serverless.\r\n\r\n\r\n## Notes\r\n\r\n* Added schema that will forbid this setting in serverless environments\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"615c16ec8a692ea8125811141045504ff40157fe"}},"sourceBranch":"main","suggestedTargetBranches":["8.12","8.11"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","branchLabelMappingKey":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/175029","number":175029,"mergeCommit":{"message":"[HTTP] Allow default resolution to be used for certain internal routes (#175029)\n\n## Summary\r\n\r\nWhen we rolled out the ability to create versioned routes the version\r\nparameters for internal routes became mandatory. However, there are\r\nseveral past instances where users integrating with Kibana come to rely\r\non routes intended for internal access only, and developers may not be\r\naware of this reliance.\r\n\r\nIn very select cases where passing version params (via headers) is not\r\npossible or cumbersome it would be useful to lift the breaking change\r\nrather than force users to, for example, abandon an upgrade.\r\n\r\nThus, this piece of advanced user config\r\n`useDefaultResolutionStrategyForInternalPaths` is added to enable the\r\ndefault version resolution to be used on select internal paths. Use\r\nlike:\r\n\r\n```yaml\r\nserver.versioned.useVersionResolutionStrategyForInternalPaths: ['/cool_path/{id?}']\r\n```\r\n\r\n\r\n## How to test\r\n\r\n* Start Kibana with the following in `kibana.dev.yml`\r\n\r\n```yaml\r\nserver.versioned:\r\n useVersionResolutionStrategyForInternalPaths: ['/internal/fleet/reset_preconfigured_agent_policies']\r\n versionResolution: 'oldest'\r\n```\r\n\r\n* Run this cURL command (assuming no base path mode)\r\n\r\n```sh\r\ncurl -uelastic:changeme http://localhost:5601/internal/fleet/reset_preconfigured_agent_policies -H 'content-type: application/json' -H 'kbn-xsrf: true' -d '{}'\r\n```\r\n\r\n* Your request should receive `200`\r\n\r\nDo the same but removing `useDefaultResolutionStrategyForInternalPaths`\r\nshould result in `400` with an error about version parameter missing.\r\n\r\n## Risks\r\n<!--\r\nProvide a matrix or statement of known risks and how they are mitigated.\r\nSee risk examples:\r\nhttps://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx\r\n-->\r\n\r\n* Configuration is not used as intended or is relied upon by users. The\r\nlikelihood is **low** but severity **high**. To mitigate this, the\r\nconfiguration is designed to be cumbersome and, likely, to break over\r\ntime as internal paths evolve. Additionally the configuration is\r\ndisabled for serverless.\r\n\r\n\r\n## Notes\r\n\r\n* Added schema that will forbid this setting in serverless environments\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"615c16ec8a692ea8125811141045504ff40157fe"}},{"branch":"8.11","label":"v8.11.4","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Jean-Louis Leysens <jeanlouis.leysens@elastic.co>
This commit is contained in:
parent
5ddfaa60ef
commit
e1a0931d84
15 changed files with 205 additions and 23 deletions
|
@ -15,7 +15,10 @@ const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {});
|
|||
|
||||
const routerOptions: RouterOptions = {
|
||||
isDev: false,
|
||||
versionedRouteResolution: 'oldest',
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'oldest',
|
||||
useVersionResolutionStrategyForInternalPaths: [],
|
||||
},
|
||||
};
|
||||
|
||||
describe('Router', () => {
|
||||
|
|
|
@ -123,11 +123,14 @@ function validOptions(
|
|||
export interface RouterOptions {
|
||||
/** Whether we are running in development */
|
||||
isDev?: boolean;
|
||||
/**
|
||||
* Which route resolution algo to use.
|
||||
* @note default to "oldest", but when running in dev default to "none"
|
||||
*/
|
||||
versionedRouteResolution?: 'newest' | 'oldest' | 'none';
|
||||
|
||||
versionedRouterOptions?: {
|
||||
/** {@inheritdoc VersionedRouterArgs['defaultHandlerResolutionStrategy'] }*/
|
||||
defaultHandlerResolutionStrategy?: 'newest' | 'oldest' | 'none';
|
||||
|
||||
/** {@inheritdoc VersionedRouterArgs['useVersionResolutionStrategyForInternalPaths'] }*/
|
||||
useVersionResolutionStrategyForInternalPaths?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -252,7 +255,7 @@ export class Router<Context extends RequestHandlerContextBase = RequestHandlerCo
|
|||
this.versionedRouter = CoreVersionedRouter.from({
|
||||
router: this,
|
||||
isDev: this.options.isDev,
|
||||
defaultHandlerResolutionStrategy: this.options.versionedRouteResolution,
|
||||
...this.options.versionedRouterOptions,
|
||||
});
|
||||
}
|
||||
return this.versionedRouter;
|
||||
|
|
|
@ -258,4 +258,68 @@ describe('Versioned route', () => {
|
|||
expect(validatedOutputBody).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('allows using default resolution for specific internal routes', async () => {
|
||||
const versionedRouter = CoreVersionedRouter.from({
|
||||
router,
|
||||
isDev: true,
|
||||
useVersionResolutionStrategyForInternalPaths: ['/bypass_me/{id?}'],
|
||||
});
|
||||
|
||||
let bypassVersionHandler: RequestHandler;
|
||||
(router.post as jest.Mock).mockImplementation(
|
||||
(opts: unknown, fn) => (bypassVersionHandler = fn)
|
||||
);
|
||||
versionedRouter.post({ path: '/bypass_me/{id?}', access: 'internal' }).addVersion(
|
||||
{
|
||||
version: '1',
|
||||
validate: false,
|
||||
},
|
||||
handlerFn
|
||||
);
|
||||
|
||||
let doNotBypassHandler1: RequestHandler;
|
||||
(router.put as jest.Mock).mockImplementation((opts: unknown, fn) => (doNotBypassHandler1 = fn));
|
||||
versionedRouter.put({ path: '/do_not_bypass_me/{id}', access: 'internal' }).addVersion(
|
||||
{
|
||||
version: '1',
|
||||
validate: false,
|
||||
},
|
||||
handlerFn
|
||||
);
|
||||
|
||||
let doNotBypassHandler2: RequestHandler;
|
||||
(router.get as jest.Mock).mockImplementation((opts: unknown, fn) => (doNotBypassHandler2 = fn));
|
||||
versionedRouter.get({ path: '/do_not_bypass_me_either', access: 'internal' }).addVersion(
|
||||
{
|
||||
version: '1',
|
||||
validate: false,
|
||||
},
|
||||
handlerFn
|
||||
);
|
||||
|
||||
const byPassedVersionResponse = await bypassVersionHandler!(
|
||||
{} as any,
|
||||
createRequest({ version: undefined }),
|
||||
responseFactory
|
||||
);
|
||||
|
||||
const doNotBypassResponse1 = await doNotBypassHandler1!(
|
||||
{} as any,
|
||||
createRequest({ version: undefined }),
|
||||
responseFactory
|
||||
);
|
||||
|
||||
const doNotBypassResponse2 = await doNotBypassHandler2!(
|
||||
{} as any,
|
||||
createRequest({ version: undefined }),
|
||||
responseFactory
|
||||
);
|
||||
|
||||
expect(byPassedVersionResponse.status).toBe(200);
|
||||
expect(doNotBypassResponse1.status).toBe(400);
|
||||
expect(doNotBypassResponse1.payload).toMatch('Please specify a version');
|
||||
expect(doNotBypassResponse2.status).toBe(400);
|
||||
expect(doNotBypassResponse2.payload).toMatch('Please specify a version');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -70,6 +70,7 @@ export class CoreVersionedRoute implements VersionedRoute {
|
|||
return new CoreVersionedRoute(router, method, path, options);
|
||||
}
|
||||
|
||||
private useDefaultStrategyForPath: boolean;
|
||||
private isPublic: boolean;
|
||||
private enableQueryVersion: boolean;
|
||||
private constructor(
|
||||
|
@ -78,6 +79,7 @@ export class CoreVersionedRoute implements VersionedRoute {
|
|||
public readonly path: string,
|
||||
public readonly options: VersionedRouteConfig<Method>
|
||||
) {
|
||||
this.useDefaultStrategyForPath = router.useVersionResolutionStrategyForInternalPaths.has(path);
|
||||
this.isPublic = this.options.access === 'public';
|
||||
this.enableQueryVersion = this.options.enableQueryVersion === true;
|
||||
this.router.router[this.method](
|
||||
|
@ -121,7 +123,7 @@ export class CoreVersionedRoute implements VersionedRoute {
|
|||
let version: undefined | ApiVersion;
|
||||
|
||||
const maybeVersion = readVersion(req, this.enableQueryVersion);
|
||||
if (!maybeVersion && this.isPublic) {
|
||||
if (!maybeVersion && (this.isPublic || this.useDefaultStrategyForPath)) {
|
||||
version = this.getDefaultVersion();
|
||||
} else {
|
||||
version = maybeVersion;
|
||||
|
|
|
@ -12,23 +12,59 @@ import { CoreVersionedRoute } from './core_versioned_route';
|
|||
import type { HandlerResolutionStrategy, Method, VersionedRouterRoute } from './types';
|
||||
|
||||
/** @internal */
|
||||
interface Dependencies {
|
||||
export interface VersionedRouterArgs {
|
||||
router: IRouter;
|
||||
/**
|
||||
* Which route resolution algo to use.
|
||||
* @note default to "oldest", but when running in dev default to "none"
|
||||
*/
|
||||
defaultHandlerResolutionStrategy?: HandlerResolutionStrategy;
|
||||
/** Whether Kibana is running in a dev environment */
|
||||
isDev?: boolean;
|
||||
/**
|
||||
* List of internal paths that should use the default handler resolution strategy. By default this
|
||||
* is no routes ([]) because ONLY Elastic clients are intended to call internal routes.
|
||||
*
|
||||
* @note Relaxing this requirement for a path may lead to unspecified behavior because internal
|
||||
* routes, do not use this unless needed!
|
||||
*
|
||||
* @note This is intended as a workaround. For example: users who have in
|
||||
* error come to rely on internal functionality and cannot easily pass a version
|
||||
* and need a workaround.
|
||||
*
|
||||
* @note Exact matches are performed against the paths as registered against the router
|
||||
*
|
||||
* @default []
|
||||
*/
|
||||
useVersionResolutionStrategyForInternalPaths?: string[];
|
||||
}
|
||||
|
||||
export class CoreVersionedRouter implements VersionedRouter {
|
||||
private readonly routes = new Set<CoreVersionedRoute>();
|
||||
public static from({ router, defaultHandlerResolutionStrategy, isDev }: Dependencies) {
|
||||
return new CoreVersionedRouter(router, defaultHandlerResolutionStrategy, isDev);
|
||||
public readonly useVersionResolutionStrategyForInternalPaths: Map<string, boolean> = new Map();
|
||||
public static from({
|
||||
router,
|
||||
defaultHandlerResolutionStrategy,
|
||||
isDev,
|
||||
useVersionResolutionStrategyForInternalPaths,
|
||||
}: VersionedRouterArgs) {
|
||||
return new CoreVersionedRouter(
|
||||
router,
|
||||
defaultHandlerResolutionStrategy,
|
||||
isDev,
|
||||
useVersionResolutionStrategyForInternalPaths
|
||||
);
|
||||
}
|
||||
private constructor(
|
||||
public readonly router: IRouter,
|
||||
public readonly defaultHandlerResolutionStrategy: HandlerResolutionStrategy = 'oldest',
|
||||
public readonly isDev: boolean = false
|
||||
) {}
|
||||
public readonly isDev: boolean = false,
|
||||
useVersionResolutionStrategyForInternalPaths: string[] = []
|
||||
) {
|
||||
for (const path of useVersionResolutionStrategyForInternalPaths) {
|
||||
this.useVersionResolutionStrategyForInternalPaths.set(path, true);
|
||||
}
|
||||
}
|
||||
|
||||
private registerVersionedRoute =
|
||||
(routeMethod: Method) =>
|
||||
|
|
|
@ -128,6 +128,7 @@ Object {
|
|||
},
|
||||
"versioned": Object {
|
||||
"strictClientVersionCheck": true,
|
||||
"useVersionResolutionStrategyForInternalPaths": Array [],
|
||||
"versionResolution": "oldest",
|
||||
},
|
||||
"xsrf": Object {
|
||||
|
|
|
@ -203,6 +203,12 @@ const configSchema = schema.object(
|
|||
* same-build browsers can access the Kibana server.
|
||||
*/
|
||||
strictClientVersionCheck: schema.boolean({ defaultValue: true }),
|
||||
|
||||
/** This should not be configurable in serverless */
|
||||
useVersionResolutionStrategyForInternalPaths: offeringBasedSchema({
|
||||
traditional: schema.arrayOf(schema.string(), { defaultValue: [] }),
|
||||
serverless: schema.never(),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
{
|
||||
|
@ -280,6 +286,7 @@ export class HttpConfig implements IHttpConfig {
|
|||
public versioned: {
|
||||
versionResolution: HandlerResolutionStrategy;
|
||||
strictClientVersionCheck: boolean;
|
||||
useVersionResolutionStrategyForInternalPaths: string[];
|
||||
};
|
||||
public shutdownTimeout: Duration;
|
||||
public restrictInternalApis: boolean;
|
||||
|
|
|
@ -33,7 +33,10 @@ import { of, Observable, BehaviorSubject } from 'rxjs';
|
|||
|
||||
const routerOptions: RouterOptions = {
|
||||
isDev: false,
|
||||
versionedRouteResolution: 'oldest',
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'oldest',
|
||||
useVersionResolutionStrategyForInternalPaths: [],
|
||||
},
|
||||
};
|
||||
|
||||
const cookieOptions = {
|
||||
|
|
|
@ -450,6 +450,7 @@ test('passes versioned config to router', async () => {
|
|||
versioned: {
|
||||
versionResolution: 'newest',
|
||||
strictClientVersionCheck: false,
|
||||
useVersionResolutionStrategyForInternalPaths: ['/foo'],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -481,6 +482,12 @@ test('passes versioned config to router', async () => {
|
|||
'/foo',
|
||||
expect.any(Object), // logger
|
||||
expect.any(Function), // context enhancer
|
||||
expect.objectContaining({ isDev: true, versionedRouteResolution: 'newest' })
|
||||
expect.objectContaining({
|
||||
isDev: true,
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'newest',
|
||||
useVersionResolutionStrategyForInternalPaths: ['/foo'],
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ import type {
|
|||
InternalContextSetup,
|
||||
InternalContextPreboot,
|
||||
} from '@kbn/core-http-context-server-internal';
|
||||
import { Router } from '@kbn/core-http-router-server-internal';
|
||||
import { Router, RouterOptions } from '@kbn/core-http-router-server-internal';
|
||||
|
||||
import { CspConfigType, cspConfig } from './csp';
|
||||
import { HttpConfig, HttpConfigType, config as httpConfig } from './http_config';
|
||||
|
@ -132,7 +132,10 @@ export class HttpService
|
|||
path,
|
||||
this.log,
|
||||
prebootServerRequestHandlerContext.createHandler.bind(null, this.coreContext.coreId),
|
||||
{ isDev: this.env.mode.dev, versionedRouteResolution: config.versioned.versionResolution }
|
||||
{
|
||||
isDev: this.env.mode.dev,
|
||||
versionedRouterOptions: getVersionedRouterOptions(config),
|
||||
}
|
||||
);
|
||||
|
||||
registerCallback(router);
|
||||
|
@ -178,7 +181,7 @@ export class HttpService
|
|||
const enhanceHandler = this.requestHandlerContext!.createHandler.bind(null, pluginId);
|
||||
const router = new Router<Context>(path, this.log, enhanceHandler, {
|
||||
isDev: this.env.mode.dev,
|
||||
versionedRouteResolution: config.versioned.versionResolution,
|
||||
versionedRouterOptions: getVersionedRouterOptions(config),
|
||||
});
|
||||
registerRouter(router);
|
||||
return router;
|
||||
|
@ -248,3 +251,11 @@ export class HttpService
|
|||
await this.httpsRedirectServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
function getVersionedRouterOptions(config: HttpConfig): RouterOptions['versionedRouterOptions'] {
|
||||
return {
|
||||
defaultHandlerResolutionStrategy: config.versioned.versionResolution,
|
||||
useVersionResolutionStrategyForInternalPaths:
|
||||
config.versioned.useVersionResolutionStrategyForInternalPaths,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -57,7 +57,9 @@ describe('Http server', () => {
|
|||
|
||||
const router = new Router('', logger, enhanceWithContext, {
|
||||
isDev: false,
|
||||
versionedRouteResolution: 'oldest',
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'oldest',
|
||||
},
|
||||
});
|
||||
router.post(
|
||||
{
|
||||
|
|
|
@ -378,6 +378,7 @@ describe('core lifecycle handlers with no strict client version check', () => {
|
|||
versioned: {
|
||||
strictClientVersionCheck: false,
|
||||
versionResolution: 'newest',
|
||||
useVersionResolutionStrategyForInternalPaths: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -2058,7 +2058,9 @@ describe('registerRouterAfterListening', () => {
|
|||
|
||||
const otherRouter = new Router('/test', loggerMock.create(), enhanceWithContext, {
|
||||
isDev: false,
|
||||
versionedRouteResolution: 'oldest',
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'oldest',
|
||||
},
|
||||
});
|
||||
otherRouter.get({ path: '/afterListening', validate: false }, (context, req, res) => {
|
||||
return res.ok({ body: 'hello from other router' });
|
||||
|
@ -2093,7 +2095,9 @@ describe('registerRouterAfterListening', () => {
|
|||
|
||||
const otherRouter = new Router('/test', loggerMock.create(), enhanceWithContext, {
|
||||
isDev: false,
|
||||
versionedRouteResolution: 'oldest',
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'oldest',
|
||||
},
|
||||
});
|
||||
otherRouter.get({ path: '/afterListening', validate: false }, (context, req, res) => {
|
||||
return res.ok({ body: 'hello from other router' });
|
||||
|
|
|
@ -62,7 +62,9 @@ describe('HttpServer - TLS config', () => {
|
|||
|
||||
const router = new Router('', logger, enhanceWithContext, {
|
||||
isDev: false,
|
||||
versionedRouteResolution: 'oldest',
|
||||
versionedRouterOptions: {
|
||||
defaultHandlerResolutionStrategy: 'oldest',
|
||||
},
|
||||
});
|
||||
router.get(
|
||||
{
|
||||
|
|
|
@ -23,17 +23,23 @@ import { ELASTIC_HTTP_VERSION_QUERY_PARAM } from '@kbn/core-http-common';
|
|||
let server: HttpService;
|
||||
let logger: ReturnType<typeof loggingSystemMock.create>;
|
||||
|
||||
interface AdditionalOptions {
|
||||
useVersionResolutionStrategyForInternalPaths?: string[];
|
||||
}
|
||||
|
||||
describe('Routing versioned requests', () => {
|
||||
let router: IRouter;
|
||||
let supertest: Supertest.SuperTest<Supertest.Test>;
|
||||
|
||||
async function setupServer(cliArgs: Partial<CliArgs> = {}) {
|
||||
async function setupServer(cliArgs: Partial<CliArgs> = {}, options: AdditionalOptions = {}) {
|
||||
logger = loggingSystemMock.create();
|
||||
await server?.stop(); // stop the already started server
|
||||
const serverConfig: Partial<HttpConfigType> = {
|
||||
versioned: {
|
||||
versionResolution: cliArgs.dev ? 'none' : cliArgs.serverless ? 'newest' : 'oldest',
|
||||
strictClientVersionCheck: !cliArgs.serverless,
|
||||
useVersionResolutionStrategyForInternalPaths:
|
||||
options.useVersionResolutionStrategyForInternalPaths ?? [],
|
||||
},
|
||||
};
|
||||
server = createHttpServer({
|
||||
|
@ -499,4 +505,34 @@ describe('Routing versioned requests', () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('defaults version parameters for select internal paths', async () => {
|
||||
await setupServer(
|
||||
{},
|
||||
{ useVersionResolutionStrategyForInternalPaths: ['/my_path_to_bypass/{id?}'] }
|
||||
);
|
||||
|
||||
router.versioned
|
||||
.get({ path: '/my_path_to_bypass/{id?}', access: 'internal' })
|
||||
.addVersion({ validate: false, version: '1' }, async (ctx, req, res) => {
|
||||
return res.ok({ body: { ok: true } });
|
||||
});
|
||||
router.versioned
|
||||
.get({ path: '/my_other_path', access: 'internal' })
|
||||
.addVersion({ validate: false, version: '1' }, async (ctx, req, res) => {
|
||||
return res.ok({ body: { ok: true } });
|
||||
});
|
||||
|
||||
await server.start();
|
||||
|
||||
await supertest.get('/my_path_to_bypass/123').expect(200);
|
||||
const response = await supertest.get('/my_other_path').expect(400);
|
||||
|
||||
expect(response).toMatchObject({
|
||||
status: 400,
|
||||
body: {
|
||||
message: expect.stringContaining('Please specify a version'),
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue