-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HTTP] Versioned router implementation #153543
Merged
Merged
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
30c31e1
move types to "core-versioned-http-server"
jloleysens 52aff31
rename "version" to "versioned" in all files
jloleysens e5a80bc
export types
jloleysens 1e88fac
remove the concept of versioned http toolkit
jloleysens 1d28474
remove concept of versioned toolkit from code
jloleysens b191455
added getRoutes function and moved required "access" property to top-…
jloleysens 3b74e08
Added VersionedRouterRoute type
jloleysens d720fdf
one small step for versioned http
jloleysens 2124cae
added some check for "not found" 406 responses
jloleysens 5a76452
move to "from" pattern for internal versioned router
jloleysens dc6b41b
update index exports
jloleysens 1890a96
update index exports
jloleysens 51f63db
updated types a bit more
jloleysens 256a47f
got first iteration of the versioned router working, need a lot more …
jloleysens 78a9e59
ran yarn kbn bootstrap
jloleysens 02f7eef
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine a2601b2
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine 929b3ef
remove export of non-existent types
jloleysens 7422334
moved types to core-http-server, bye bye boilerplate
jloleysens 9a751f2
move implementation to core/http
jloleysens f9241f6
run yarn kbn bootstrap and moved some internal types to internal package
jloleysens 879575b
remove unhelpful comment
jloleysens f76be86
remove unnecessary type cast
jloleysens c83fdea
fix jest config and rename Internal... to Core...
jloleysens 83d1d48
register route in the contstructor
jloleysens fd84e23
improve readbility of nullish checking
jloleysens 3a7dfb7
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine 2bbc777
added some more tests
jloleysens 91d54bf
updated test message
jloleysens 82a2147
clean making the core request mutable
jloleysens 3e79036
Merge branch 'main' into versioned-router-impl
jloleysens ae1a918
add "type" to type only import
jloleysens 991984d
added status code to body result
jloleysens e7f3b6d
Pass in the mutated request
jloleysens d0363a3
improve if statement to run validation if there is at least some inpu…
jloleysens 4ebba29
use mutable kibana request
jloleysens ff4c755
Merge branch 'main' into versioned-router-impl
jloleysens 2970540
slight update to types
jloleysens 0cf0319
added internal comment and updated test
jloleysens 9e2e542
Merge branch 'main' into versioned-router-impl
jloleysens 9ae403e
remove example.ts file, move to doc comment
jloleysens abb110d
refactor names of some versioning specific types
jloleysens 7abb5da
fix ts issue
jloleysens File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 1 addition & 3 deletions
4
...ioning/core-version-http-server/README.md → ...core-http-server/src/versioning/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
packages/core/http/core-http-server/src/versioning/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
export type { | ||
ApiVersion, | ||
AddVersionOpts, | ||
VersionedRouteRequestValidation, | ||
VersionedRouteResponseValidation, | ||
VersionedRoute, | ||
VersionedRouteConfig, | ||
VersionedRouteRegistrar, | ||
VersionedRouter, | ||
} from './types'; |
225 changes: 225 additions & 0 deletions
225
packages/core/http/core-http-server/src/versioning/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import type { Type } from '@kbn/config-schema'; | ||
import type { MaybePromise } from '@kbn/utility-types'; | ||
import type { | ||
RouteConfig, | ||
RouteMethod, | ||
RequestHandler, | ||
IKibanaResponse, | ||
RouteConfigOptions, | ||
RouteValidatorFullConfig, | ||
RequestHandlerContextBase, | ||
RouteValidationFunction, | ||
} from '../..'; | ||
|
||
type RqCtx = RequestHandlerContextBase; | ||
|
||
/** | ||
* Assuming that version will be a monotonically increasing number where: version > 0. | ||
* @experimental | ||
*/ | ||
export type ApiVersion = `${number}`; | ||
|
||
/** | ||
* Configuration for a versioned route | ||
* @experimental | ||
*/ | ||
export type VersionedRouteConfig<Method extends RouteMethod> = Omit< | ||
RouteConfig<unknown, unknown, unknown, Method>, | ||
'validate' | 'options' | ||
> & { | ||
options?: Omit<RouteConfigOptions<Method>, 'access'>; | ||
/** See {@link RouteConfigOptions<RouteMethod>['access']} */ | ||
access: RouteConfigOptions<Method>['access']; | ||
}; | ||
|
||
/** | ||
* Create an {@link VersionedRoute | versioned route}. | ||
* | ||
* @param config - The route configuration | ||
* @returns A versioned route | ||
* @experimental | ||
*/ | ||
export type VersionedRouteRegistrar<Method extends RouteMethod, Ctx extends RqCtx = RqCtx> = ( | ||
config: VersionedRouteConfig<Method> | ||
) => VersionedRoute<Method, Ctx>; | ||
|
||
/** | ||
* A router, very similar to {@link IRouter} that will return an {@link VersionedRoute} | ||
* instead. | ||
* | ||
* @example | ||
* const versionedRoute = versionedRouter | ||
* .post({ | ||
* access: 'internal', | ||
* path: '/api/my-app/foo/{id?}', | ||
* options: { timeout: { payload: 60000 } }, | ||
* }) | ||
* .addVersion( | ||
* { | ||
* version: '1', | ||
* validate: { | ||
* request: { | ||
* query: schema.object({ | ||
* name: schema.maybe(schema.string({ minLength: 2, maxLength: 50 })), | ||
* }), | ||
* params: schema.object({ | ||
* id: schema.maybe(schema.string({ minLength: 10, maxLength: 13 })), | ||
* }), | ||
* body: schema.object({ foo: schema.string() }), | ||
* }, | ||
* response: { | ||
* 200: { | ||
* body: schema.object({ foo: schema.string() }), | ||
* }, | ||
* }, | ||
* }, | ||
* }, | ||
* async (ctx, req, res) => { | ||
* await ctx.fooService.create(req.body.foo, req.params.id, req.query.name); | ||
* return res.ok({ body: { foo: req.body.foo } }); | ||
* } | ||
* ) | ||
* // BREAKING CHANGE: { foo: string } => { fooString: string } in body | ||
* .addVersion( | ||
* { | ||
* version: '2', | ||
* validate: { | ||
* request: { | ||
* query: schema.object({ | ||
* name: schema.maybe(schema.string({ minLength: 2, maxLength: 50 })), | ||
* }), | ||
* params: schema.object({ | ||
* id: schema.maybe(schema.string({ minLength: 10, maxLength: 13 })), | ||
* }), | ||
* body: schema.object({ fooString: schema.string() }), | ||
* }, | ||
* response: { | ||
* 200: { | ||
* body: schema.object({ fooName: schema.string() }), | ||
* }, | ||
* }, | ||
* }, | ||
* }, | ||
* async (ctx, req, res) => { | ||
* await ctx.fooService.create(req.body.fooString, req.params.id, req.query.name); | ||
* return res.ok({ body: { fooName: req.body.fooString } }); | ||
* } | ||
* ) | ||
* // BREAKING CHANGES: Enforce min/max length on fooString | ||
* .addVersion( | ||
* { | ||
* version: '3', | ||
* validate: { | ||
* request: { | ||
* query: schema.object({ | ||
* name: schema.maybe(schema.string({ minLength: 2, maxLength: 50 })), | ||
* }), | ||
* params: schema.object({ | ||
* id: schema.maybe(schema.string({ minLength: 10, maxLength: 13 })), | ||
* }), | ||
* body: schema.object({ fooString: schema.string({ minLength: 0, maxLength: 1000 }) }), | ||
* }, | ||
* response: { | ||
* 200: { | ||
* body: schema.object({ fooName: schema.string() }), | ||
* }, | ||
* }, | ||
* }, | ||
* }, | ||
* async (ctx, req, res) => { | ||
* await ctx.fooService.create(req.body.fooString, req.params.id, req.query.name); | ||
* return res.ok({ body: { fooName: req.body.fooString } }); | ||
* } | ||
* ); | ||
|
||
* @experimental | ||
*/ | ||
export interface VersionedRouter<Ctx extends RqCtx = RqCtx> { | ||
/** @experimental */ | ||
get: VersionedRouteRegistrar<'get', Ctx>; | ||
/** @experimental */ | ||
put: VersionedRouteRegistrar<'put', Ctx>; | ||
/** @experimental */ | ||
post: VersionedRouteRegistrar<'post', Ctx>; | ||
/** @experimental */ | ||
patch: VersionedRouteRegistrar<'patch', Ctx>; | ||
/** @experimental */ | ||
delete: VersionedRouteRegistrar<'delete', Ctx>; | ||
} | ||
|
||
/** @experimental */ | ||
export type VersionedRouteRequestValidation<P, Q, B> = RouteValidatorFullConfig<P, Q, B>; | ||
|
||
/** @experimental */ | ||
export interface VersionedRouteResponseValidation<R> { | ||
[statusCode: number]: { body: RouteValidationFunction<R> | Type<R> }; | ||
unsafe?: { body?: boolean }; | ||
} | ||
|
||
/** | ||
* Versioned route validation | ||
* @experimental | ||
*/ | ||
interface FullValidationConfig<P, Q, B, R> { | ||
/** | ||
* Validation to run against route inputs: params, query and body | ||
* @experimental | ||
*/ | ||
request?: VersionedRouteRequestValidation<P, Q, B>; | ||
/** | ||
* Validation to run against route output | ||
* @note This validation is only intended to run in development. Do not use this | ||
* for setting default values! | ||
* @experimental | ||
*/ | ||
response?: VersionedRouteResponseValidation<R>; | ||
} | ||
|
||
/** | ||
* Options for a versioned route. Probably needs a lot more options like sunsetting | ||
* of an endpoint etc. | ||
* @experimental | ||
*/ | ||
export interface AddVersionOpts<P, Q, B, R> { | ||
/** | ||
* Version to assign to this route | ||
* @experimental | ||
*/ | ||
version: ApiVersion; | ||
/** | ||
* Validation for this version of a route | ||
* @experimental | ||
*/ | ||
validate: false | FullValidationConfig<P, Q, B, R>; | ||
} | ||
|
||
/** | ||
* A versioned route | ||
* @experimental | ||
*/ | ||
export interface VersionedRoute< | ||
Method extends RouteMethod = RouteMethod, | ||
Ctx extends RqCtx = RqCtx | ||
> { | ||
/** | ||
* Add a new version of this route | ||
* @param opts {@link AddVersionOpts | Options} for this version of a route | ||
* @param handler The request handler for this version of a route | ||
* @returns A versioned route, allows for fluent chaining of version declarations | ||
* @experimental | ||
*/ | ||
addVersion<P = unknown, Q = unknown, B = unknown, R = any>( | ||
options: AddVersionOpts<P, Q, B, R>, | ||
handler: ( | ||
...params: Parameters<RequestHandler<P, Q, B, Ctx>> | ||
) => MaybePromise<IKibanaResponse<R>> | ||
): VersionedRoute<Method, Ctx>; | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/core/http/core-http-versioned-router-server-internal/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# @kbn/core-http-versioned-router-server-internal | ||
|
||
This package contains the implementation for sever-side HTTP versioning. | ||
|
||
## Experimental | ||
|
||
See notes in `@kbn/core-http-server/src/versioning` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ing/core-version-http-server/kibana.jsonc → ...ioned-router-server-internal/kibana.jsonc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"type": "shared-common", | ||
"id": "@kbn/core-version-http-server", | ||
"id": "@kbn/core-http-versioned-router-server-internal", | ||
"owner": "@elastic/kibana-core" | ||
} |
2 changes: 1 addition & 1 deletion
2
...ing/core-version-http-server/package.json → ...ioned-router-server-internal/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following OAS's example here. For the responses we added validation for specific status codes. At the moment this is used to scope validation to a specific status code, but we could go further and throw if an unknown status code was provided.
Note: output validation is intended to run in dev only.