Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
0f60357
rename files
jloleysens Jan 30, 2024
4c45365
moved some files around and added functionality for inject SHA digest
jloleysens Jan 30, 2024
f8b22e9
pass (mock)env to HTTP server
jloleysens Jan 30, 2024
10507b6
buildShaShort
jloleysens Jan 30, 2024
74dc468
use the new variable
jloleysens Jan 30, 2024
619dcd8
tests for buildShaShort
jloleysens Jan 30, 2024
e5a0afc
allow registering multiple paths
jloleysens Jan 30, 2024
7a16c10
changed approach; serve plugin static assets from both paths
jloleysens Jan 30, 2024
2562311
introduce and use prependServerPath
jloleysens Jan 30, 2024
16574ad
fix registerBundleRoutes
jloleysens Jan 31, 2024
e69de75
pass static assets to bundle register function
jloleysens Jan 31, 2024
d9e7bb8
fix export
jloleysens Jan 31, 2024
7e08c0d
fix suffixPathnameToPathaname and added tests
jloleysens Jan 31, 2024
38ec92c
double register core ui static assets
jloleysens Jan 31, 2024
b2f8e91
added comment
jloleysens Jan 31, 2024
bc9f977
added test for registering double paths
jloleysens Jan 31, 2024
9534a42
added tests for plugin static dir registration
jloleysens Jan 31, 2024
b8fa60e
fix tests
jloleysens Jan 31, 2024
06dc28d
updated a lot of rendering jest test snapshots
jloleysens Jan 31, 2024
2d4a3c9
use build sha
jloleysens Jan 31, 2024
44fa9ce
fix types
jloleysens Jan 31, 2024
9c4b4ae
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jan 31, 2024
ef0a3e4
use build hash in FTR tests
jloleysens Jan 31, 2024
9af7d08
satisfy types
jloleysens Jan 31, 2024
ec3cbb1
satisfy types
jloleysens Feb 1, 2024
eb14f4d
Merge branch 'main' into http/remove-replace-buildnr-with-sha
jloleysens Feb 1, 2024
dea7748
buildNum -> buildHash in test
jloleysens Feb 1, 2024
59d91e0
use static assets from core instead of hardcoded paths
jloleysens Feb 1, 2024
95db53c
added append to public URL pathname to public server static assets
jloleysens Feb 1, 2024
b45d980
Merge branch 'main' into http/remove-replace-buildnr-with-sha
jloleysens Feb 1, 2024
5ecb585
satisfy types
jloleysens Feb 1, 2024
f0f534f
satisfy types
jloleysens Feb 1, 2024
1103fc3
satisfy types
jloleysens Feb 2, 2024
05f0cd7
added a couple of comments
jloleysens Feb 2, 2024
eca5fb2
Merge branch 'main' into http/remove-replace-buildnr-with-sha
jloleysens Feb 2, 2024
8149b73
added comment
jloleysens Feb 2, 2024
97f0435
added stricter CDN URL checks given existing assumptions
jloleysens Feb 2, 2024
368d5e7
append => prepend, renaming appropriately
jloleysens Feb 2, 2024
dab7de2
pass core context!
jloleysens Feb 2, 2024
b979170
kwargs
jloleysens Feb 2, 2024
32a27ae
update require
jloleysens Feb 2, 2024
74086e3
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Feb 2, 2024
bf147b8
Merge branch 'main' into http/remove-replace-buildnr-with-sha
kibanamachine Feb 5, 2024
1451a3f
Merge branch 'main' into http/remove-replace-buildnr-with-sha
jloleysens Feb 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const PAGE_VARS_KEYS = [

// Deployment-specific keys
'version', // x4, split to version_major, version_minor, version_patch for easier filtering
'buildNum', // May be useful for Serverless
'buildNum', // May be useful for Serverless, TODO: replace with buildHash
'cloudId',
'deploymentId',
'projectId', // projectId and deploymentId are mutually exclusive. They shouldn't be sent in the same offering.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import { httpServiceMock } from '@kbn/core-http-server-mocks';
import type { InternalPluginInfo, UiPlugins } from '@kbn/core-plugins-base-server-internal';
import { registerBundleRoutes } from './register_bundle_routes';
import { FileHashCache } from './file_hash_cache';
import { BasePath, StaticAssets } from '@kbn/core-http-server-internal';

const createPackageInfo = (parts: Partial<PackageInfo> = {}): PackageInfo => ({
buildNum: 42,
buildSha: 'sha',
buildSha: 'shasha',
buildShaShort: 'sha',
dist: true,
branch: 'master',
version: '8.0.0',
Expand All @@ -41,9 +43,12 @@ const createUiPlugins = (...ids: string[]): UiPlugins => ({

describe('registerBundleRoutes', () => {
let router: ReturnType<typeof httpServiceMock.createRouter>;
let staticAssets: StaticAssets;

beforeEach(() => {
router = httpServiceMock.createRouter();
const basePath = httpServiceMock.createBasePath('/server-base-path') as unknown as BasePath;
staticAssets = new StaticAssets({ basePath, cdnConfig: {} as any, shaDigest: 'sha' });
});

afterEach(() => {
Expand All @@ -53,7 +58,7 @@ describe('registerBundleRoutes', () => {
it('registers core and shared-dep bundles', () => {
registerBundleRoutes({
router,
serverBasePath: '/server-base-path',
staticAssets,
packageInfo: createPackageInfo(),
uiPlugins: createUiPlugins(),
});
Expand All @@ -64,39 +69,39 @@ describe('registerBundleRoutes', () => {
fileHashCache: expect.any(FileHashCache),
isDist: true,
bundlesPath: 'uiSharedDepsSrcDistDir',
publicPath: '/server-base-path/42/bundles/kbn-ui-shared-deps-src/',
routePath: '/42/bundles/kbn-ui-shared-deps-src/',
publicPath: '/server-base-path/sha/bundles/kbn-ui-shared-deps-src/',
routePath: '/sha/bundles/kbn-ui-shared-deps-src/',
});

expect(registerRouteForBundleMock).toHaveBeenCalledWith(router, {
fileHashCache: expect.any(FileHashCache),
isDist: true,
bundlesPath: 'uiSharedDepsNpmDistDir',
publicPath: '/server-base-path/42/bundles/kbn-ui-shared-deps-npm/',
routePath: '/42/bundles/kbn-ui-shared-deps-npm/',
publicPath: '/server-base-path/sha/bundles/kbn-ui-shared-deps-npm/',
routePath: '/sha/bundles/kbn-ui-shared-deps-npm/',
});

expect(registerRouteForBundleMock).toHaveBeenCalledWith(router, {
fileHashCache: expect.any(FileHashCache),
isDist: true,
bundlesPath: expect.stringMatching(/\/@kbn\/core\/target\/public$/),
publicPath: '/server-base-path/42/bundles/core/',
routePath: '/42/bundles/core/',
publicPath: '/server-base-path/sha/bundles/core/',
routePath: '/sha/bundles/core/',
});

expect(registerRouteForBundleMock).toHaveBeenCalledWith(router, {
fileHashCache: expect.any(FileHashCache),
isDist: true,
bundlesPath: 'kbnMonacoBundleDir',
publicPath: '/server-base-path/42/bundles/kbn-monaco/',
routePath: '/42/bundles/kbn-monaco/',
publicPath: '/server-base-path/sha/bundles/kbn-monaco/',
routePath: '/sha/bundles/kbn-monaco/',
});
});

it('registers plugin bundles', () => {
registerBundleRoutes({
router,
serverBasePath: '/server-base-path',
staticAssets,
packageInfo: createPackageInfo(),
uiPlugins: createUiPlugins('plugin-a', 'plugin-b'),
});
Expand All @@ -107,16 +112,16 @@ describe('registerBundleRoutes', () => {
fileHashCache: expect.any(FileHashCache),
isDist: true,
bundlesPath: '/plugins/plugin-a/public-target-dir',
publicPath: '/server-base-path/42/bundles/plugin/plugin-a/8.0.0/',
routePath: '/42/bundles/plugin/plugin-a/8.0.0/',
publicPath: '/server-base-path/sha/bundles/plugin/plugin-a/8.0.0/',
routePath: '/sha/bundles/plugin/plugin-a/8.0.0/',
});

expect(registerRouteForBundleMock).toHaveBeenCalledWith(router, {
fileHashCache: expect.any(FileHashCache),
isDist: true,
bundlesPath: '/plugins/plugin-b/public-target-dir',
publicPath: '/server-base-path/42/bundles/plugin/plugin-b/8.0.0/',
routePath: '/42/bundles/plugin/plugin-b/8.0.0/',
publicPath: '/server-base-path/sha/bundles/plugin/plugin-b/8.0.0/',
routePath: '/sha/bundles/plugin/plugin-b/8.0.0/',
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { distDir as UiSharedDepsSrcDistDir } from '@kbn/ui-shared-deps-src';
import * as KbnMonaco from '@kbn/monaco/server';
import type { IRouter } from '@kbn/core-http-server';
import type { UiPlugins } from '@kbn/core-plugins-base-server-internal';
import { InternalStaticAssets } from '@kbn/core-http-server-internal';
import { FileHashCache } from './file_hash_cache';
import { registerRouteForBundle } from './bundles_route';

Expand All @@ -28,56 +29,61 @@ import { registerRouteForBundle } from './bundles_route';
*/
export function registerBundleRoutes({
router,
serverBasePath,
uiPlugins,
packageInfo,
staticAssets,
}: {
router: IRouter;
serverBasePath: string;
uiPlugins: UiPlugins;
packageInfo: PackageInfo;
staticAssets: InternalStaticAssets;
}) {
const { dist: isDist, buildNum } = packageInfo;
const { dist: isDist } = packageInfo;
// rather than calculate the fileHash on every request, we
// provide a cache object to `resolveDynamicAssetResponse()` that
// will store the most recently used hashes.
const fileHashCache = new FileHashCache();

const sharedNpmDepsPath = '/bundles/kbn-ui-shared-deps-npm/';
registerRouteForBundle(router, {
publicPath: `${serverBasePath}/${buildNum}/bundles/kbn-ui-shared-deps-npm/`,
routePath: `/${buildNum}/bundles/kbn-ui-shared-deps-npm/`,
publicPath: staticAssets.prependPublicUrl(sharedNpmDepsPath) + '/',
routePath: staticAssets.prependServerPath(sharedNpmDepsPath) + '/',
bundlesPath: UiSharedDepsNpm.distDir,
fileHashCache,
isDist,
});
const sharedDepsPath = '/bundles/kbn-ui-shared-deps-src/';
registerRouteForBundle(router, {
publicPath: `${serverBasePath}/${buildNum}/bundles/kbn-ui-shared-deps-src/`,
routePath: `/${buildNum}/bundles/kbn-ui-shared-deps-src/`,
publicPath: staticAssets.prependPublicUrl(sharedDepsPath) + '/',
routePath: staticAssets.prependServerPath(sharedDepsPath) + '/',
bundlesPath: UiSharedDepsSrcDistDir,
fileHashCache,
isDist,
});
const coreBundlePath = '/bundles/core/';
registerRouteForBundle(router, {
publicPath: `${serverBasePath}/${buildNum}/bundles/core/`,
routePath: `/${buildNum}/bundles/core/`,
publicPath: staticAssets.prependPublicUrl(coreBundlePath) + '/',
routePath: staticAssets.prependServerPath(coreBundlePath) + '/',
bundlesPath: isDist
? fromRoot('node_modules/@kbn/core/target/public')
: fromRoot('src/core/target/public'),
fileHashCache,
isDist,
});
const monacoEditorPath = '/bundles/kbn-monaco/';
registerRouteForBundle(router, {
publicPath: `${serverBasePath}/${buildNum}/bundles/kbn-monaco/`,
routePath: `/${buildNum}/bundles/kbn-monaco/`,
publicPath: staticAssets.prependPublicUrl(monacoEditorPath) + '/',
routePath: staticAssets.prependServerPath(monacoEditorPath) + '/',
bundlesPath: KbnMonaco.bundleDir,
fileHashCache,
isDist,
});

[...uiPlugins.internal.entries()].forEach(([id, { publicTargetDir, version }]) => {
const pluginBundlesPath = `/bundles/plugin/${id}/${version}/`;
registerRouteForBundle(router, {
publicPath: `${serverBasePath}/${buildNum}/bundles/plugin/${id}/${version}/`,
routePath: `/${buildNum}/bundles/plugin/${id}/${version}/`,
publicPath: staticAssets.prependPublicUrl(pluginBundlesPath) + '/',
routePath: staticAssets.prependServerPath(pluginBundlesPath) + '/',
bundlesPath: publicTargetDir,
fileHashCache,
isDist,
Expand Down
22 changes: 19 additions & 3 deletions packages/core/apps/core-apps-server-internal/src/core_app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { httpResourcesMock } from '@kbn/core-http-resources-server-mocks';
import { PluginType } from '@kbn/core-base-common';
import type { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server';
import { coreInternalLifecycleMock } from '@kbn/core-lifecycle-server-mocks';
import { CoreAppsService } from './core_app';
import { of } from 'rxjs';
import { CoreAppsService } from './core_app';

const emptyPlugins = (): UiPlugins => ({
internal: new Map(),
Expand Down Expand Up @@ -146,7 +146,7 @@ describe('CoreApp', () => {
uiPlugins: prebootUIPlugins,
router: expect.any(Object),
packageInfo: coreContext.env.packageInfo,
serverBasePath: internalCorePreboot.http.basePath.serverBasePath,
staticAssets: expect.any(Object),
});
});

Expand Down Expand Up @@ -245,7 +245,23 @@ describe('CoreApp', () => {
uiPlugins,
router: expect.any(Object),
packageInfo: coreContext.env.packageInfo,
serverBasePath: internalCoreSetup.http.basePath.serverBasePath,
staticAssets: expect.any(Object),
});
});

it('registers SHA-scoped and non-SHA-scoped UI bundle routes', async () => {
const uiPlugins = emptyPlugins();
internalCoreSetup.http.staticAssets.prependServerPath.mockReturnValue('/some-path');
await coreApp.setup(internalCoreSetup, uiPlugins);

expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledTimes(2);
expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith(
'/some-path',
expect.any(String)
);
expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith(
'/ui/{path*}',
expect.any(String)
);
});
});
23 changes: 17 additions & 6 deletions packages/core/apps/core-apps-server-internal/src/core_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
import type { UiPlugins } from '@kbn/core-plugins-base-server-internal';
import type { HttpResources, HttpResourcesServiceToolkit } from '@kbn/core-http-resources-server';
import type { InternalCorePreboot, InternalCoreSetup } from '@kbn/core-lifecycle-server-internal';
import type { InternalStaticAssets } from '@kbn/core-http-server-internal';
import { firstValueFrom, map, type Observable } from 'rxjs';
import { CoreAppConfig, type CoreAppConfigType, CoreAppPath } from './core_app_config';
import { registerBundleRoutes } from './bundle_routes';
Expand All @@ -33,6 +34,7 @@ interface CommonRoutesParams {
httpResources: HttpResources;
basePath: IBasePath;
uiPlugins: UiPlugins;
staticAssets: InternalStaticAssets;
onResourceNotFound: (
req: KibanaRequest,
res: HttpResourcesServiceToolkit & KibanaResponseFactory
Expand Down Expand Up @@ -77,10 +79,11 @@ export class CoreAppsService {
this.registerCommonDefaultRoutes({
basePath: corePreboot.http.basePath,
httpResources: corePreboot.httpResources.createRegistrar(router),
staticAssets: corePreboot.http.staticAssets,
router,
uiPlugins,
onResourceNotFound: async (req, res) =>
// THe API consumers might call various Kibana APIs (e.g. `/api/status`) when Kibana is still at the preboot
// The API consumers might call various Kibana APIs (e.g. `/api/status`) when Kibana is still at the preboot
// stage, and the main HTTP server that registers API handlers isn't up yet. At this stage we don't know if
// the API endpoint exists or not, and hence cannot reply with `404`. We also should not reply with completely
// unexpected response (`200 text/html` for the Core app). The only suitable option is to reply with `503`
Expand Down Expand Up @@ -125,6 +128,7 @@ export class CoreAppsService {
this.registerCommonDefaultRoutes({
basePath: coreSetup.http.basePath,
httpResources: resources,
staticAssets: coreSetup.http.staticAssets,
router,
uiPlugins,
onResourceNotFound: async (req, res) => res.notFound(),
Expand Down Expand Up @@ -210,6 +214,7 @@ export class CoreAppsService {
private registerCommonDefaultRoutes({
router,
basePath,
staticAssets,
uiPlugins,
onResourceNotFound,
httpResources,
Expand Down Expand Up @@ -259,17 +264,23 @@ export class CoreAppsService {
registerBundleRoutes({
router,
uiPlugins,
staticAssets,
packageInfo: this.env.packageInfo,
serverBasePath: basePath.serverBasePath,
});
}

// After the package is built and bootstrap extracts files to bazel-bin,
// assets are exposed at the root of the package and in the package's node_modules dir
private registerStaticDirs(core: InternalCoreSetup | InternalCorePreboot) {
core.http.registerStaticDir(
'/ui/{path*}',
fromRoot('node_modules/@kbn/core-apps-server-internal/assets')
);
/**
* Serve UI from sha-scoped and not-sha-scoped paths to allow time for plugin code to migrate
* Eventually we only want to serve from the sha scoped path
*/
[core.http.staticAssets.prependServerPath('/ui/{path*}'), '/ui/{path*}'].forEach((path) => {
core.http.registerStaticDir(
path,
fromRoot('node_modules/@kbn/core-apps-server-internal/assets')
);
});
}
}
1 change: 1 addition & 0 deletions packages/core/apps/core-apps-server-internal/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@kbn/core-lifecycle-server-mocks",
"@kbn/core-ui-settings-server",
"@kbn/monaco",
"@kbn/core-http-server-internal",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function createCoreContext({ production = false }: { production?: boolean } = {}
branch: 'branch',
buildNum: 100,
buildSha: 'buildSha',
buildShaShort: 'buildShaShort',
dist: false,
buildDate: new Date('2023-05-15T23:12:09.000Z'),
buildFlavor: 'traditional',
Expand Down
1 change: 1 addition & 0 deletions packages/core/http/core-http-server-internal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type {
InternalHttpServiceStart,
} from './src/types';
export { BasePath } from './src/base_path_service';
export { type InternalStaticAssets, StaticAssets } from './src/static_assets';

export { cspConfig, CspConfig, type CspConfigType } from './src/csp';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Side Public License, v 1.
*/

import { CdnConfig } from './cdn';
import { CdnConfig } from './cdn_config';

describe('CdnConfig', () => {
it.each([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ export interface Input {
}

export class CdnConfig {
private url: undefined | URL;
private readonly url: undefined | URL;
constructor(url?: string) {
if (url) {
this.url = new URL(url); // This will throw for invalid URLs
this.url = new URL(url); // This will throw for invalid URLs, although should be validated before reaching this point
}
}

public get host(): undefined | string {
return this.url?.host ?? undefined;
return this.url?.host;
}

public get baseHref(): undefined | string {
Expand Down
Loading