Skip to content
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

Merged
merged 29 commits into from
Jan 15, 2025
Merged

Conversation

jloleysens
Copy link
Contributor

@jloleysens jloleysens commented Jan 3, 2025

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 new InternalRouterRoute that expects internal handlers to map (hapi)Request -> IKibanaResponse instead of CoreKibanaRequest -> 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 to HapiResponseObject.

(3) Reduce the size of the router.ts file. Quite a bit of implementation moved to route.ts or util.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.

@jloleysens jloleysens added Feature:http Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc release_note:skip Skip the PR/issue when compiling release notes v9.0.0 backport:version Backport to applied version labels v8.18.0 labels Jan 3, 2025
@jloleysens jloleysens self-assigned this Jan 3, 2025
Copy link
Contributor Author

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 KibanaRequests, validation and emitting of router events)
(2) slim down the size of the ./router.ts file

});
});

it('emits post validation events on the router', () => {
Copy link
Contributor Author

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(
Copy link
Contributor Author

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

Comment on lines 57 to 61
export const passThroughValidation = {
body: schema.nullable(schema.any()),
params: schema.nullable(schema.any()),
query: schema.nullable(schema.any()),
};
Copy link
Contributor Author

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 }
Copy link
Contributor Author

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, {
Copy link
Contributor Author

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'> & {
Copy link
Contributor Author

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)

@jloleysens
Copy link
Contributor Author

/ci

@jloleysens
Copy link
Contributor Author

/ci

Copy link
Contributor

@TinaHeiligers TinaHeiligers left a 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!

src/core/packages/http/router-server-internal/src/util.ts Outdated Show resolved Hide resolved
@@ -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.
Copy link
Contributor

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

Copy link
Contributor

@pgayvallet pgayvallet left a 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.

Copy link
Contributor

@elena-shostak elena-shostak left a 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 👍

Copy link
Member

@Bamieh Bamieh left a 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.

@Bamieh
Copy link
Member

Bamieh commented Jan 13, 2025

@elasticmachine merge upstream

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/core-http-server 242 243 +1
Unknown metric groups

API count

id before after diff
@kbn/core-http-server 567 568 +1

History

cc @jloleysens

@jloleysens jloleysens merged commit ca77772 into elastic:main Jan 15, 2025
8 checks passed
@jloleysens jloleysens deleted the http/refactor-versioned-router branch January 15, 2025 15:10
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/12791260143

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.x Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 205502

Questions ?

Please refer to the Backport tool documentation

@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jan 17, 2025
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add a backport:* label or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 205502 locally

2 similar comments
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add a backport:* label or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 205502 locally

@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add a backport:* label or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 205502 locally

jloleysens added a commit to jloleysens/kibana that referenced this pull request Jan 22, 2025
(cherry picked from commit ca77772)

# Conflicts:
#	src/core/packages/http/router-server-internal/src/router.ts
@jloleysens
Copy link
Contributor Author

💚 All backports created successfully

Status Branch Result
8.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

jloleysens added a commit that referenced this pull request Jan 22, 2025
# 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-->
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jan 22, 2025
viduni94 pushed a commit to viduni94/kibana that referenced this pull request Jan 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:version Backport to applied version labels Feature:http release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v8.18.0 v9.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants