-
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] Router refactor #205502
[Http] Router refactor #205502
Conversation
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.
99% of the added logic in this file comes from ./router.ts
and aims to create simple functions to:
(1) create better reusability of these lower level functionalities between router and versioned router (specifically, creating KibanaRequest
s, validation and emitting of router events)
(2) slim down the size of the ./router.ts
file
}); | ||
}); | ||
|
||
it('emits post validation events on the router', () => { |
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.
This is new test coverage
@@ -92,3 +95,76 @@ export function getVersionHeader(version: string): ResponseHeaders { | |||
export function injectVersionHeader(version: string, response: IKibanaResponse): IKibanaResponse { | |||
return injectResponseHeaders(getVersionHeader(version), response); | |||
} | |||
|
|||
export function formatErrorMeta( |
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.
These functions were airlifted out of ./router.ts
export const passThroughValidation = { | ||
body: schema.nullable(schema.any()), | ||
params: schema.nullable(schema.any()), | ||
query: schema.nullable(schema.any()), | ||
}; |
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.
This is an important change of this refactor, bc we have an InternalRouteHandler
that allows for more distinct route vs versioned route implementations we can avoid the "handler in a handler" flow that existed before causing us to run validation twice (once pass through, once for real).
security: this.getSecurity, | ||
}, | ||
this.requestHandler, | ||
{ isVersioned: true, events: false } |
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.
Another change: removal of opaque option events
that created conditional flows behind indirection
|
||
this.router.emitPostValidate(req, postValidateMetadata); | ||
return res.badRequest({ body: e.message, headers: getVersionHeader(version) }); | ||
const { error, ok: validatedRequest } = validateHapiRequest(hapiRequest, { |
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.
Use the same validation flow as route.ts
|
||
return { ...options, body }; | ||
} | ||
export type InternalRouterRoute = Omit<RouterRoute, 'handler'> & { |
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.
Sort of the main change of this refactor, see PR description (1) & (2)
/ci |
/ci |
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.
router refactor:
Nice work handling debt debt while allowing more freedom for internal route owners!
I agree that we'll have some duplication, and we'll keep an eye on it so that things don't stray too far or get out of hand.
I left a nit and comment, completely optional.
Overall, looks great!
@@ -214,3 +214,8 @@ export interface KibanaRequest< | |||
*/ | |||
readonly body: Body; | |||
} | |||
|
|||
/** | |||
* @remark Convenience type, use when the concrete values of P, Q, B and route method do not matter. |
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.
WDYT about adding a typical example of when concrete values don't matter? It might help prevent unintended use of AnyKibanaRequest
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.
Great to see this happening. I agree that it moves complexity around, and sometimes brings a bit of duplication in the logic between our 2 router impls, but the freedom it brings is worth it ihmo, as it makes sure that we won't be limited by our own public-facing router hapi when implementing internals ever again.
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.
Checked security config - LGTM 👍
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.
LGTM! I paid special attention to the emitPostValidate
and isVersioned
changes since this is where some things diverged in the previous layered implementaiton.
@elasticmachine merge upstream |
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
History
cc @jloleysens |
Starting backport for target branches: 8.x |
💔 All backports failed
Manual backportTo create the backport manually run:
Questions ?Please refer to the Backport tool documentation |
Friendly reminder: Looks like this PR hasn’t been backported yet. |
2 similar comments
Friendly reminder: Looks like this PR hasn’t been backported yet. |
Friendly reminder: Looks like this PR hasn’t been backported yet. |
(cherry picked from commit ca77772) # Conflicts: # src/core/packages/http/router-server-internal/src/router.ts
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
# Backport This will backport the following commits from `main` to `8.x`: - [[Http] Router refactor (#205502)](#205502) <!--- Backport version: 9.6.4 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Jean-Louis Leysens","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-01-15T15:10:46Z","message":"[Http] Router refactor (#205502)","sha":"ca77772d2ad5db6bb1c7b9412845e59d7a59d3ac","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:http","Team:Core","release_note:skip","backport missing","v9.0.0","backport:version","v8.18.0"],"title":"[Http] Router refactor","number":205502,"url":"https://github.com/elastic/kibana/pull/205502","mergeCommit":{"message":"[Http] Router refactor (#205502)","sha":"ca77772d2ad5db6bb1c7b9412845e59d7a59d3ac"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/205502","number":205502,"mergeCommit":{"message":"[Http] Router refactor (#205502)","sha":"ca77772d2ad5db6bb1c7b9412845e59d7a59d3ac"}},{"branch":"8.x","label":"v8.18.0","branchLabelMappingKey":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
Summary
This refactor changes only internal implementation details. (Versioned) Router functionality should be unchanged.
The goals of this refactor:
(1) The versioned router uses the "external" facing
IRouter
APIs to register it's routes creating a situation where our internal router logic lives in the same conceptual space as consumer code. This is OK, but we had to have some weird dependency passing and pass-through validation to get this to work. This refactor basically removes that.(2) Allow route registration to happen without specifying validation schemas. This required the route and versioned route to handle (hapi)
Request
objects, but ultimately gives more implementation freedom. The trade off is that there is potential for more code duplication, but I think with factored out functionality this can be well-tested and kept to an acceptable minimum. The current iteration actually improves our DRY metric slightly 😉. Achieved with newInternalRouterRoute
that expects internal handlers to map(hapi)Request -> IKibanaResponse
instead ofCoreKibanaRequest -> IKibanaResponse
allowing internal handlers more freedom for handling requests (like validation) while still giving the "top-level" internal handler ability to run some checks before mapping toHapiResponseObject
.(3) Reduce the size of the
router.ts
file. Quite a bit of implementation moved toroute.ts
orutil.ts
(4) Add missing test coverage. We added
Router.events
a while ago to power detection of deprecated route usages and added a "post validation" request event that required updating the router. This refactor allows more functionality to be shared and better tested for both route and versioned route.Risks
Moderate level of risk. This refactor moves around code and attempts to co-locate things that were separated. In the process subtle order-of-execution bugs (or omission) may creep in... Somewhat mitigated by tests.