1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Add fakes to lensFetch and fetch to simulate lower internal routing

- Bypasses setting up the server

- Still doesn't cover the proxying to kube api

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-03-22 10:49:50 -04:00
parent 0e012b3558
commit e3a80d40bb
46 changed files with 301 additions and 112 deletions

27
package-lock.json generated
View File

@ -3080,6 +3080,15 @@
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
}, },
"node_modules/@hapi/shot": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-6.0.1.tgz",
"integrity": "sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA==",
"dependencies": {
"@hapi/hoek": "^11.0.2",
"@hapi/validate": "^2.0.1"
}
},
"node_modules/@hapi/subtext": { "node_modules/@hapi/subtext": {
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.1.0.tgz", "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.1.0.tgz",
@ -3120,6 +3129,23 @@
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
}, },
"node_modules/@hapi/validate": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-2.0.1.tgz",
"integrity": "sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==",
"dependencies": {
"@hapi/hoek": "^11.0.2",
"@hapi/topo": "^6.0.1"
}
},
"node_modules/@hapi/validate/node_modules/@hapi/topo": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz",
"integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==",
"dependencies": {
"@hapi/hoek": "^11.0.2"
}
},
"node_modules/@hapi/vise": { "node_modules/@hapi/vise": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz", "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz",
@ -34349,6 +34375,7 @@
"dependencies": { "dependencies": {
"@astronautlabs/jsonpath": "^1.1.0", "@astronautlabs/jsonpath": "^1.1.0",
"@hapi/call": "^9.0.1", "@hapi/call": "^9.0.1",
"@hapi/shot": "^6.0.1",
"@hapi/subtext": "^7.1.0", "@hapi/subtext": "^7.1.0",
"@k8slens/cluster-settings": "^6.5.0-alpha.1", "@k8slens/cluster-settings": "^6.5.0-alpha.1",
"@k8slens/node-fetch": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1",

View File

@ -119,6 +119,7 @@
"dependencies": { "dependencies": {
"@astronautlabs/jsonpath": "^1.1.0", "@astronautlabs/jsonpath": "^1.1.0",
"@hapi/call": "^9.0.1", "@hapi/call": "^9.0.1",
"@hapi/shot": "^6.0.1",
"@hapi/subtext": "^7.1.0", "@hapi/subtext": "^7.1.0",
"@k8slens/cluster-settings": "^6.5.0-alpha.1", "@k8slens/cluster-settings": "^6.5.0-alpha.1",
"@k8slens/node-fetch": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1",

View File

@ -3,31 +3,27 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import lensFetchInjectable from "../fetch/lens-fetch.injectable";
import loggerInjectable from "../logger.injectable";
import { apiPrefix } from "../vars"; import { apiPrefix } from "../vars";
import isDebuggingInjectable from "../vars/is-debugging.injectable";
import isDevelopmentInjectable from "../vars/is-development.injectable";
import { apiBaseHostHeaderInjectionToken, apiBaseServerAddressInjectionToken } from "./api-base-configs"; import { apiBaseHostHeaderInjectionToken, apiBaseServerAddressInjectionToken } from "./api-base-configs";
import createJsonApiInjectable from "./create-json-api.injectable"; import isApiBaseInDebugModeInjectable from "./is-api-in-debug-mode.injectable";
import { JsonApi } from "./json-api";
const apiBaseInjectable = getInjectable({ const apiBaseInjectable = getInjectable({
id: "api-base", id: "api-base",
instantiate: (di) => { instantiate: (di) => new JsonApi({
const createJsonApi = di.inject(createJsonApiInjectable); fetch: di.inject(lensFetchInjectable),
const isDebugging = di.inject(isDebuggingInjectable); logger: di.inject(loggerInjectable),
const isDevelopment = di.inject(isDevelopmentInjectable); }, {
const serverAddress = di.inject(apiBaseServerAddressInjectionToken); serverAddress: di.inject(apiBaseServerAddressInjectionToken),
const hostHeaderValue = di.inject(apiBaseHostHeaderInjectionToken); apiBase: apiPrefix,
debug: di.inject(isApiBaseInDebugModeInjectable),
return createJsonApi({ }, {
serverAddress, headers: {
apiBase: apiPrefix, "Host": di.inject(apiBaseHostHeaderInjectionToken),
debug: isDevelopment || isDebugging, },
}, { }),
headers: {
"Host": hostHeaderValue,
},
});
},
}); });
export default apiBaseInjectable; export default apiBaseInjectable;

View File

@ -3,13 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { Agent } from "https";
import type { RequestInit } from "@k8slens/node-fetch"; import type { RequestInit } from "@k8slens/node-fetch";
import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable";
import fetchInjectable from "../fetch/fetch.injectable"; import fetchInjectable from "../fetch/fetch.injectable";
import loggerInjectable from "../logger.injectable"; import loggerInjectable from "../logger.injectable";
import type { JsonApiConfig, JsonApiData, JsonApiDependencies, JsonApiParams } from "./json-api"; import type { JsonApiConfig, JsonApiData, JsonApiDependencies, JsonApiParams } from "./json-api";
import { JsonApi } from "./json-api"; import { JsonApi } from "./json-api";
import lensAgentInjectable from "./lens-agent.injectable";
export type CreateJsonApi = <Data = JsonApiData, Params extends JsonApiParams<Data> = JsonApiParams<Data>>(config: JsonApiConfig, reqInit?: RequestInit) => JsonApi<Data, Params>; export type CreateJsonApi = <Data = JsonApiData, Params extends JsonApiParams<Data> = JsonApiParams<Data>>(config: JsonApiConfig, reqInit?: RequestInit) => JsonApi<Data, Params>;
@ -20,20 +19,11 @@ const createJsonApiInjectable = getInjectable({
fetch: di.inject(fetchInjectable), fetch: di.inject(fetchInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
}; };
const lensProxyCert = di.inject(lensProxyCertificateInjectable);
return (config, reqInit) => { return (config, reqInit) => {
if (!config.getRequestOptions) { config.getRequestOptions ??= async () => ({
config.getRequestOptions = async () => { agent: di.inject(lensAgentInjectable),
const agent = new Agent({ });
ca: lensProxyCert.get().cert,
});
return {
agent,
};
};
}
return new JsonApi(deps, config, reqInit); return new JsonApi(deps, config, reqInit);
}; };

View File

@ -3,13 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { Agent } from "https";
import type { RequestInit } from "@k8slens/node-fetch"; import type { RequestInit } from "@k8slens/node-fetch";
import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable";
import fetchInjectable from "../fetch/fetch.injectable"; import fetchInjectable from "../fetch/fetch.injectable";
import loggerInjectable from "../logger.injectable"; import loggerInjectable from "../logger.injectable";
import type { JsonApiConfig, JsonApiDependencies } from "./json-api"; import type { JsonApiConfig, JsonApiDependencies } from "./json-api";
import { KubeJsonApi } from "./kube-json-api"; import { KubeJsonApi } from "./kube-json-api";
import lensAgentInjectable from "./lens-agent.injectable";
export type CreateKubeJsonApi = (config: JsonApiConfig, reqInit?: RequestInit) => KubeJsonApi; export type CreateKubeJsonApi = (config: JsonApiConfig, reqInit?: RequestInit) => KubeJsonApi;
@ -20,21 +19,12 @@ const createKubeJsonApiInjectable = getInjectable({
fetch: di.inject(fetchInjectable), fetch: di.inject(fetchInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
}; };
const lensProxyCert = di.inject(lensProxyCertificateInjectable);
return (config, reqInit) => { return (config, reqInit) => {
if (!config.getRequestOptions) { config.getRequestOptions ??= async () => ({
config.getRequestOptions = async () => { agent: di.inject(lensAgentInjectable),
const agent = new Agent({ });
ca: lensProxyCert.get().cert,
});
return {
agent,
};
};
}
return new KubeJsonApi(dependencies, config, reqInit); return new KubeJsonApi(dependencies, config, reqInit);
}; };
}, },

View File

@ -0,0 +1,14 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import isDebuggingInjectable from "../vars/is-debugging.injectable";
import isDevelopmentInjectable from "../vars/is-development.injectable";
const isApiBaseInDebugModeInjectable = getInjectable({
id: "is-api-base-in-debug-mode",
instantiate: (di) => di.inject(isDebuggingInjectable) || di.inject(isDevelopmentInjectable),
});
export default isApiBaseInDebugModeInjectable;

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { Agent } from "https";
import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable";
const lensAgentInjectable = getInjectable({
id: "lens-agent",
instantiate: (di) => {
const lensProxyCert = di.inject(lensProxyCertificateInjectable);
return new Agent({
ca: lensProxyCert.get().cert,
});
},
});
export default lensAgentInjectable;

View File

@ -9,7 +9,6 @@ import { createContainer, isInjectable } from "@ogre-tools/injectable";
import spawnInjectable from "./child-process/spawn.injectable"; import spawnInjectable from "./child-process/spawn.injectable";
import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable"; import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable";
import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable"; import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable";
import setupLensProxyInjectable from "./start-main-application/runnables/setup-lens-proxy.injectable";
import setupSyncingOfWeblinksInjectable from "../features/weblinks/main/setup-syncing-of-weblinks.injectable"; import setupSyncingOfWeblinksInjectable from "../features/weblinks/main/setup-syncing-of-weblinks.injectable";
import setupDeepLinkingInjectable from "./electron-app/runnables/setup-deep-linking.injectable"; import setupDeepLinkingInjectable from "./electron-app/runnables/setup-deep-linking.injectable";
import setupMainWindowVisibilityAfterActivationInjectable from "./electron-app/runnables/setup-main-window-visibility-after-activation.injectable"; import setupMainWindowVisibilityAfterActivationInjectable from "./electron-app/runnables/setup-main-window-visibility-after-activation.injectable";
@ -88,7 +87,6 @@ const overrideRunnablesHavingSideEffects = (di: DiContainer) => {
initializeExtensionsInjectable, initializeExtensionsInjectable,
initializeClusterManagerInjectable, initializeClusterManagerInjectable,
setupIpcMainHandlersInjectable, setupIpcMainHandlersInjectable,
setupLensProxyInjectable,
setupSyncingOfWeblinksInjectable, setupSyncingOfWeblinksInjectable,
].forEach((injectable) => { ].forEach((injectable) => {
di.override(injectable, () => ({ di.override(injectable, () => ({

View File

@ -3,7 +3,6 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { AddressInfo } from "net";
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable"; import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
import loggerInjectable from "../../common/logger.injectable"; import loggerInjectable from "../../common/logger.injectable";
import lensProxyHttpsServerInjectable from "./https-proxy/server.injectable"; import lensProxyHttpsServerInjectable from "./https-proxy/server.injectable";
@ -30,7 +29,7 @@ const attemptToListenInjectable = getInjectable({
.once("listening", () => { .once("listening", () => {
proxyServer.removeAllListeners("error"); // don't reject the promise proxyServer.removeAllListeners("error"); // don't reject the promise
const { address, port } = proxyServer.address() as AddressInfo; const { address, port } = proxyServer.address();
lensProxyPort.set(port); lensProxyPort.set(port);

View File

@ -3,10 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
import type { Cluster } from "../../common/cluster/cluster";
import { getClusterIdFromHost } from "../../common/utils"; import { getClusterIdFromHost } from "../../common/utils";
import { apiKubePrefix } from "../../common/vars"; import { apiKubePrefix } from "../../common/vars";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable"; import type { ProxyIncomingMessage } from "./messages";
import type { GetClusterForRequest } from "./lens-proxy";
export type GetClusterForRequest = (req: ProxyIncomingMessage) => Cluster | undefined;
const getClusterForRequestInjectable = getInjectable({ const getClusterForRequestInjectable = getInjectable({
id: "get-cluster-for-request", id: "get-cluster-for-request",
@ -19,7 +22,7 @@ const getClusterForRequestInjectable = getInjectable({
} }
// lens-server is connecting to 127.0.0.1:<port>/<uid> // lens-server is connecting to 127.0.0.1:<port>/<uid>
if (req.url && req.headers.host.startsWith("127.0.0.1")) { if (req.headers.host.startsWith("127.0.0.1")) {
const clusterId = req.url.split("/")[1]; const clusterId = req.url.split("/")[1];
const cluster = getClusterById(clusterId); const cluster = getClusterById(clusterId);

View File

@ -6,12 +6,10 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { ServerResponse } from "http"; import type { ServerResponse } from "http";
import { apiKubePrefix } from "../../common/vars"; import { apiKubePrefix } from "../../common/vars";
import contentSecurityPolicyInjectable from "../../common/vars/content-security-policy.injectable"; import contentSecurityPolicyInjectable from "../../common/vars/content-security-policy.injectable";
import kubeAuthProxyServerInjectable from "../cluster/kube-auth-proxy-server.injectable";
import routeRequestInjectable from "../router/route-request.injectable"; import routeRequestInjectable from "../router/route-request.injectable";
import getClusterForRequestInjectable from "./get-cluster-for-request.injectable"; import getClusterForRequestInjectable from "./get-cluster-for-request.injectable";
import { isLongRunningRequest } from "./helpers";
import type { ProxyIncomingMessage } from "./messages"; import type { ProxyIncomingMessage } from "./messages";
import rawHttpProxyInjectable from "./proxy/raw-proxy.injectable"; import proxyReqToClusterInjectable from "./proxy/attempt.injectable";
export type HandleRouteRequest = (req: ProxyIncomingMessage, res: ServerResponse) => Promise<void>; export type HandleRouteRequest = (req: ProxyIncomingMessage, res: ServerResponse) => Promise<void>;
@ -20,26 +18,18 @@ const handleRouteRequestInjectable = getInjectable({
instantiate: (di): HandleRouteRequest => { instantiate: (di): HandleRouteRequest => {
const getClusterForRequest = di.inject(getClusterForRequestInjectable); const getClusterForRequest = di.inject(getClusterForRequestInjectable);
const routeRequest = di.inject(routeRequestInjectable); const routeRequest = di.inject(routeRequestInjectable);
const proxy = di.inject(rawHttpProxyInjectable);
const contentSecurityPolicy = di.inject(contentSecurityPolicyInjectable); const contentSecurityPolicy = di.inject(contentSecurityPolicyInjectable);
const proxyReqToCluster = di.inject(proxyReqToClusterInjectable);
return async (req, res) => { return async (req, res) => {
const cluster = getClusterForRequest(req); const cluster = getClusterForRequest(req);
if (cluster && req.url.startsWith(apiKubePrefix)) { if (cluster && req.url.startsWith(apiKubePrefix)) {
delete req.headers.authorization; await proxyReqToCluster(cluster, req, res);
req.url = req.url.replace(apiKubePrefix, ""); } else {
res.setHeader("Content-Security-Policy", contentSecurityPolicy);
const kubeAuthProxyServer = di.inject(kubeAuthProxyServerInjectable, cluster); await routeRequest(cluster, req, res);
const proxyTarget = await kubeAuthProxyServer.getApiTarget(isLongRunningRequest(req.url));
if (proxyTarget) {
return proxy.web(req, res, proxyTarget);
}
} }
res.setHeader("Content-Security-Policy", contentSecurityPolicy);
await routeRequest(cluster, req, res);
}; };
}, },
}); });

View File

@ -0,0 +1,22 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "@k8slens/test-utils";
import EventEmitter from "events";
import lensProxyHttpsServerInjectable from "./server.injectable";
export default getGlobalOverride(lensProxyHttpsServerInjectable, () => new class extends EventEmitter {
close() { }
listen() {
this.emit("listening");
}
address() {
return {
address: "https://localhost:9090",
port: 9090,
family: "some-family",
};
}
});

View File

@ -8,6 +8,20 @@ import lensProxyCertificateInjectable from "../../../common/certificate/lens-pro
import handleRouteRequestInjectable from "../handle-route-request.injectable"; import handleRouteRequestInjectable from "../handle-route-request.injectable";
import lensProxyHttpsServerOnUpgradeInjectable from "./on-upgrade.injectable"; import lensProxyHttpsServerOnUpgradeInjectable from "./on-upgrade.injectable";
import { ProxyIncomingMessage } from "../messages"; import { ProxyIncomingMessage } from "../messages";
import type { AddressInfo } from "net";
export interface LensProxyHttpsServer {
close(): void;
listen(port: number, hostname: string): void;
once(event: "listening", listener: () => void): LensProxyHttpsServer;
once(event: "error", listener: (error: Error) => void): LensProxyHttpsServer;
on(event: "listening", listener: () => void): LensProxyHttpsServer;
on(event: "error", listener: (error: Error) => void): LensProxyHttpsServer;
off(event: "listening", listener: () => void): LensProxyHttpsServer;
off(event: "error", listener: (error: Error) => void): LensProxyHttpsServer;
removeAllListeners(event: "error" | "listening"): void;
address(): AddressInfo;
}
const lensProxyHttpsServerInjectable = getInjectable({ const lensProxyHttpsServerInjectable = getInjectable({
id: "lens-proxy-https-server", id: "lens-proxy-https-server",
@ -23,8 +37,9 @@ const lensProxyHttpsServerInjectable = getInjectable({
server.on("upgrade", di.inject(lensProxyHttpsServerOnUpgradeInjectable)); server.on("upgrade", di.inject(lensProxyHttpsServerOnUpgradeInjectable));
return server; return server as LensProxyHttpsServer;
}, },
causesSideEffects: true,
}); });
export default lensProxyHttpsServerInjectable; export default lensProxyHttpsServerInjectable;

View File

@ -1,5 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export * from "./types";

View File

@ -9,9 +9,9 @@ import { connect } from "tls";
import url, { URL } from "url"; import url, { URL } from "url";
import { apiKubePrefix } from "../../../common/vars"; import { apiKubePrefix } from "../../../common/vars";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { LensProxyApiRequest } from "../lens-proxy";
import kubeAuthProxyServerInjectable from "../../cluster/kube-auth-proxy-server.injectable"; import kubeAuthProxyServerInjectable from "../../cluster/kube-auth-proxy-server.injectable";
import kubeAuthProxyCertificateInjectable from "../../kube-auth-proxy/kube-auth-proxy-certificate.injectable"; import kubeAuthProxyCertificateInjectable from "../../kube-auth-proxy/kube-auth-proxy-certificate.injectable";
import type { LensProxyApiRequest } from "./types";
const skipRawHeaders = new Set(["Host", "Authorization"]); const skipRawHeaders = new Set(["Host", "Authorization"]);

View File

@ -5,11 +5,11 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import shellRequestAuthenticatorInjectable from "./shell-request-authenticator/shell-request-authenticator.injectable"; import shellRequestAuthenticatorInjectable from "./shell-request-authenticator/shell-request-authenticator.injectable";
import openShellSessionInjectable from "../../shell-session/create-shell-session.injectable"; import openShellSessionInjectable from "../../shell-session/create-shell-session.injectable";
import type { LensProxyApiRequest } from "../lens-proxy";
import URLParse from "url-parse"; import URLParse from "url-parse";
import { Server as WebSocketServer } from "ws"; import { Server as WebSocketServer } from "ws";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import getClusterForRequestInjectable from "../get-cluster-for-request.injectable"; import getClusterForRequestInjectable from "../get-cluster-for-request.injectable";
import type { LensProxyApiRequest } from "./types";
const shellApiRequestInjectable = getInjectable({ const shellApiRequestInjectable = getInjectable({
id: "shell-api-request", id: "shell-api-request",

View File

@ -3,14 +3,15 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type http from "http";
import type net from "net"; import type net from "net";
import type { SetRequired } from "type-fest";
import type { Cluster } from "../../../common/cluster/cluster"; import type { Cluster } from "../../../common/cluster/cluster";
import type { ProxyIncomingMessage } from "../messages";
export interface ProxyApiRequestArgs { export interface ProxyApiRequestArgs {
req: SetRequired<http.IncomingMessage, "url" | "method">; req: ProxyIncomingMessage;
socket: net.Socket; socket: net.Socket;
head: Buffer; head: Buffer;
cluster: Cluster; cluster: Cluster;
} }
export type LensProxyApiRequest = (args: ProxyApiRequestArgs) => void;

View File

@ -0,0 +1,9 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverrideForFunction } from "@k8slens/test-utils";
import proxyReqToClusterInjectable from "./attempt.injectable";
export default getGlobalOverrideForFunction(proxyReqToClusterInjectable);

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ServerResponse } from "http";
import type { Cluster } from "../../../common/cluster/cluster";
import { apiKubePrefix } from "../../../common/vars";
import kubeAuthProxyServerInjectable from "../../cluster/kube-auth-proxy-server.injectable";
import { isLongRunningRequest } from "../helpers";
import type { ProxyIncomingMessage } from "../messages";
import rawHttpProxyInjectable from "./raw-proxy.injectable";
export type ProxyReqToCluster = (cluster: Cluster, req: ProxyIncomingMessage, res: ServerResponse) => Promise<void>;
const proxyReqToClusterInjectable = getInjectable({
id: "proxy-req-to-cluster",
instantiate: (di): ProxyReqToCluster => {
const proxy = di.inject(rawHttpProxyInjectable);
return async (cluster, req, res) => {
delete req.headers.authorization;
req.url = req.url.replace(apiKubePrefix, "");
const kubeAuthProxyServer = di.inject(kubeAuthProxyServerInjectable, cluster);
const proxyTarget = await kubeAuthProxyServer.getApiTarget(isLongRunningRequest(req.url));
proxy.web(req, res, proxyTarget);
};
},
causesSideEffects: true,
});
export default proxyReqToClusterInjectable;

View File

@ -10,6 +10,7 @@ import type { ProxyIncomingMessage } from "../messages";
const rawHttpProxyInjectable = getInjectable({ const rawHttpProxyInjectable = getInjectable({
id: "raw-http-proxy", id: "raw-http-proxy",
instantiate: () => createProxy<ProxyIncomingMessage>(), instantiate: () => createProxy<ProxyIncomingMessage>(),
causesSideEffects: true,
}); });
export default rawHttpProxyInjectable; export default rawHttpProxyInjectable;

View File

@ -10,8 +10,8 @@ import Call from "@hapi/call";
import Subtext from "@hapi/subtext"; import Subtext from "@hapi/subtext";
import type http from "http"; import type http from "http";
import type { Cluster } from "../../common/cluster/cluster"; import type { Cluster } from "../../common/cluster/cluster";
import type { ServerIncomingMessage } from "../lens-proxy/lens-proxy";
import type { RouteHandler } from "./create-handler-for-route.injectable"; import type { RouteHandler } from "./create-handler-for-route.injectable";
import type { ProxyIncomingMessage } from "../lens-proxy/messages";
export const routeInjectionToken = getInjectionToken<Route<unknown, string>>({ export const routeInjectionToken = getInjectionToken<Route<unknown, string>>({
id: "route-injection-token", id: "route-injection-token",
@ -26,7 +26,7 @@ export function getRouteInjectable<T, Path extends string>(
}); });
} }
export type RouteRequest = (cluster: Cluster | undefined, req: ServerIncomingMessage, res: http.ServerResponse) => Promise<boolean>; export type RouteRequest = (cluster: Cluster | undefined, req: ProxyIncomingMessage, res: http.ServerResponse) => Promise<boolean>;
const createRouter = (di: DiContainerForInjection) => { const createRouter = (di: DiContainerForInjection) => {
const routes = di.injectMany(routeInjectionToken); const routes = di.injectMany(routeInjectionToken);

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import isDevelopmentInjectable from "../../../common/vars/is-development.injectable"; import isDevelopmentInjectable from "../../../common/vars/is-development.injectable";
import { route } from "../../router/route"; import { route } from "../../router/route";
import prodStaticFileRouteHandlerInjectable from "./production.injectable"; import prodStaticFileRouteHandlerInjectable from "./production.injectable";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { route } from "../../../router/route"; import { route } from "../../../router/route";
import getHelmChartReadmeInjectable from "../../../helm/helm-service/get-helm-chart-readme.injectable"; import getHelmChartReadmeInjectable from "../../../helm/helm-service/get-helm-chart-readme.injectable";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { route } from "../../../router/route"; import { route } from "../../../router/route";
import getHelmChartValuesInjectable from "../../../helm/helm-service/get-helm-chart-values.injectable"; import getHelmChartValuesInjectable from "../../../helm/helm-service/get-helm-chart-values.injectable";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { route } from "../../../router/route"; import { route } from "../../../router/route";
import getHelmChartVersionsInjectable from "../../../helm/helm-service/get-helm-chart-versions.injectable"; import getHelmChartVersionsInjectable from "../../../helm/helm-service/get-helm-chart-versions.injectable";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { route } from "../../../router/route"; import { route } from "../../../router/route";
import listHelmChartsInjectable from "../../../helm/helm-service/list-helm-charts.injectable"; import listHelmChartsInjectable from "../../../helm/helm-service/list-helm-charts.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { clusterRoute } from "../../../router/route"; import { clusterRoute } from "../../../router/route";
import deleteClusterHelmReleaseInjectable from "../../../helm/helm-service/delete-helm-release.injectable"; import deleteClusterHelmReleaseInjectable from "../../../helm/helm-service/delete-helm-release.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { clusterRoute } from "../../../router/route"; import { clusterRoute } from "../../../router/route";
import getClusterHelmReleaseHistoryInjectable from "../../../helm/helm-service/get-helm-release-history.injectable"; import getClusterHelmReleaseHistoryInjectable from "../../../helm/helm-service/get-helm-release-history.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { clusterRoute } from "../../../router/route"; import { clusterRoute } from "../../../router/route";
import getHelmReleaseInjectable from "../../../helm/helm-service/get-helm-release.injectable"; import getHelmReleaseInjectable from "../../../helm/helm-service/get-helm-release.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { getBoolean } from "../../../utils/parse-query"; import { getBoolean } from "../../../utils/parse-query";
import { contentTypes } from "../../../router/router-content-types"; import { contentTypes } from "../../../router/router-content-types";
import { clusterRoute } from "../../../router/route"; import { clusterRoute } from "../../../router/route";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import Joi from "joi"; import Joi from "joi";
import { payloadValidatedClusterRoute } from "../../../router/route"; import { payloadValidatedClusterRoute } from "../../../router/route";
import type { InstallChartArgs } from "../../../helm/helm-service/install-helm-chart.injectable"; import type { InstallChartArgs } from "../../../helm/helm-service/install-helm-chart.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { clusterRoute } from "../../../router/route"; import { clusterRoute } from "../../../router/route";
import listClusterHelmReleasesInjectable from "../../../helm/helm-service/list-helm-releases.injectable"; import listClusterHelmReleasesInjectable from "../../../helm/helm-service/list-helm-releases.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import Joi from "joi"; import Joi from "joi";
import { payloadValidatedClusterRoute } from "../../../router/route"; import { payloadValidatedClusterRoute } from "../../../router/route";
import rollbackClusterHelmReleaseInjectable from "../../../helm/helm-service/rollback-helm-release.injectable"; import rollbackClusterHelmReleaseInjectable from "../../../helm/helm-service/rollback-helm-release.injectable";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { apiPrefix } from "../../../../common/vars"; import { apiPrefix } from "../../../../common/vars";
import { getRouteInjectable } from "../../../router/router.injectable"; import { getRouteInjectable } from "../../../router/route-request.injectable";
import { payloadValidatedClusterRoute } from "../../../router/route"; import { payloadValidatedClusterRoute } from "../../../router/route";
import Joi from "joi"; import Joi from "joi";
import type { UpdateChartArgs } from "../../../helm/helm-service/update-helm-release.injectable"; import type { UpdateChartArgs } from "../../../helm/helm-service/update-helm-release.injectable";

View File

@ -4,7 +4,7 @@
*/ */
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import type { Cluster } from "../../../common/cluster/cluster"; import type { Cluster } from "../../../common/cluster/cluster";
import type { V1Secret } from "@kubernetes/client-node"; import type { V1Secret } from "@kubernetes/client-node";
import { CoreV1Api } from "@kubernetes/client-node"; import { CoreV1Api } from "@kubernetes/client-node";

View File

@ -4,7 +4,7 @@
*/ */
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import type { ClusterPrometheusMetadata } from "../../../common/cluster-types"; import type { ClusterPrometheusMetadata } from "../../../common/cluster-types";
import { ClusterMetadataKey } from "../../../common/cluster-types"; import { ClusterMetadataKey } from "../../../common/cluster-types";
import type { Cluster } from "../../../common/cluster/cluster"; import type { Cluster } from "../../../common/cluster/cluster";

View File

@ -4,7 +4,7 @@
*/ */
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { route } from "../../router/route"; import { route } from "../../router/route";
import prometheusProvidersInjectable from "../../prometheus/providers.injectable"; import prometheusProvidersInjectable from "../../prometheus/providers.injectable";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { PortForward } from "./functionality/port-forward"; import { PortForward } from "./functionality/port-forward";
import { clusterRoute } from "../../router/route"; import { clusterRoute } from "../../router/route";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { PortForward } from "./functionality/port-forward"; import { PortForward } from "./functionality/port-forward";
import createPortForwardInjectable from "./functionality/create-port-forward.injectable"; import createPortForwardInjectable from "./functionality/create-port-forward.injectable";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { PortForward } from "./functionality/port-forward"; import { PortForward } from "./functionality/port-forward";
import { clusterRoute } from "../../router/route"; import { clusterRoute } from "../../router/route";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { payloadValidatedClusterRoute } from "../../router/route"; import { payloadValidatedClusterRoute } from "../../router/route";
import Joi from "joi"; import Joi from "joi";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { apiPrefix } from "../../../common/vars"; import { apiPrefix } from "../../../common/vars";
import { payloadValidatedClusterRoute } from "../../router/route"; import { payloadValidatedClusterRoute } from "../../router/route";
import Joi from "joi"; import Joi from "joi";

View File

@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getRouteInjectable } from "../../router/router.injectable"; import { getRouteInjectable } from "../../router/route-request.injectable";
import { route } from "../../router/route"; import { route } from "../../router/route";
import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable";

View File

@ -49,6 +49,7 @@ const setupLensProxyInjectable = getInjectable({
logger.info("⚡ LensProxy connection OK"); logger.info("⚡ LensProxy connection OK");
} catch (error) { } catch (error) {
console.log(error);
logger.error(`🛑 LensProxy: failed connection test: ${error}`); logger.error(`🛑 LensProxy: failed connection test: ${error}`);
const hostsPath = isWindows const hostsPath = isWindows
@ -69,8 +70,6 @@ const setupLensProxyInjectable = getInjectable({
runAfter: initializeBuildVersionInjectable, runAfter: initializeBuildVersionInjectable,
}), }),
causesSideEffects: true,
injectionToken: beforeApplicationIsLoadingInjectionToken, injectionToken: beforeApplicationIsLoadingInjectionToken,
}); });

View File

@ -32,7 +32,6 @@ import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTest
import assert from "assert"; import assert from "assert";
import { openMenu } from "react-select-event"; import { openMenu } from "react-select-event";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import lensProxyPortInjectable from "../../../main/lens-proxy/lens-proxy-port.injectable";
import type { Route } from "../../../common/front-end-routing/front-end-route-injection-token"; import type { Route } from "../../../common/front-end-routing/front-end-route-injection-token";
import type { NavigateToRouteOptions } from "../../../common/front-end-routing/navigate-to-route-injection-token"; import type { NavigateToRouteOptions } from "../../../common/front-end-routing/navigate-to-route-injection-token";
import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token"; import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token";
@ -72,6 +71,7 @@ import { applicationFeature, startApplicationInjectionToken } from "@k8slens/app
import { testUsingFakeTime } from "../../../test-utils/use-fake-time"; import { testUsingFakeTime } from "../../../test-utils/use-fake-time";
import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
import { getMessageBridgeFake } from "@k8slens/messaging-fake-bridge"; import { getMessageBridgeFake } from "@k8slens/messaging-fake-bridge";
import { overrideFetchingInternalRoutes } from "../../../test-utils/override-internal-backend-routes.injectable";
type MainDiCallback = (container: { mainDi: DiContainer }) => void | Promise<void>; type MainDiCallback = (container: { mainDi: DiContainer }) => void | Promise<void>;
type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise<void>; type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise<void>;
@ -192,6 +192,7 @@ export const getApplicationBuilder = () => {
const overrideFsWithFakes = getOverrideFsWithFakes(); const overrideFsWithFakes = getOverrideFsWithFakes();
overrideFsWithFakes(mainDi); overrideFsWithFakes(mainDi);
overrideFetchingInternalRoutes(mainDi);
// Set up ~/.kube as existing as a folder // Set up ~/.kube as existing as a folder
{ {
@ -235,6 +236,7 @@ export const getApplicationBuilder = () => {
messageBridgeFake.involve(windowDi); messageBridgeFake.involve(windowDi);
overrideFsWithFakes(windowDi); overrideFsWithFakes(windowDi);
overrideFetchingInternalRoutes(mainDi, windowDi);
runInAction(() => { runInAction(() => {
registerFeature( registerFeature(
@ -310,8 +312,6 @@ export const getApplicationBuilder = () => {
const startApplication = mainDi.inject(startApplicationInjectionToken); const startApplication = mainDi.inject(startApplicationInjectionToken);
const startApp = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => { const startApp = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => {
mainDi.inject(lensProxyPortInjectable).set(42);
for (const callback of beforeApplicationStartCallbacks) { for (const callback of beforeApplicationStartCallbacks) {
await callback({ mainDi }); await callback({ mainDi });
} }

View File

@ -0,0 +1,85 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { DiContainer } from "@ogre-tools/injectable";
import lensFetchInjectable from "../common/fetch/lens-fetch.injectable";
import { Headers, Response } from "@k8slens/node-fetch";
import handleRouteRequestInjectable from "../main/lens-proxy/handle-route-request.injectable";
import fetchInjectable from "../common/fetch/fetch.injectable";
import * as Shot from "@hapi/shot";
export const overrideFetchingInternalRoutes = (mainDi: DiContainer, targetDi = mainDi) => {
targetDi.override(lensFetchInjectable, () => async (pathname, init = {}) => {
// NOTE: This injects things from the other environment on purpose
const handleRouteRequest = mainDi.inject(handleRouteRequestInjectable);
const response = await Shot.inject(
handleRouteRequest as Shot.MaybeInjectionListener,
{
url: pathname,
headers: new Headers(init?.headers).raw(),
method: init?.method,
payload: init?.body ?? undefined,
},
);
return new Response(response.rawPayload, {
headers: Object.entries(response.headers).map(([key, value]) => {
if (value === undefined) {
return [key];
} else if (Array.isArray(value)) {
return [key, value.join(",")];
} else {
return [key, value.toString()];
}
}),
status: response.statusCode,
statusText: response.statusMessage,
});
});
targetDi.override(fetchInjectable, () => async (rawUrl, init = {}) => {
// NOTE: This injects things from the other environment on purpose
const handleRouteRequest = mainDi.inject(handleRouteRequestInjectable);
const url = new URL(rawUrl);
switch (url.host) {
case "localhost":
case "127.0.0.1":
case "lens.app":
break;
default:
if (url.host.endsWith(".lens.app")) {
break;
}
throw new Error("Tried to fetch an external resource");
}
const response = await Shot.inject(
handleRouteRequest as Shot.MaybeInjectionListener,
{
url: url.pathname,
headers: new Headers(init?.headers).raw(),
method: init?.method,
payload: init?.body ?? undefined,
},
);
return new Response(response.rawPayload, {
headers: Object.entries(response.headers).map(([key, value]) => {
if (value === undefined) {
return [key];
} else if (Array.isArray(value)) {
return [key, value.join(",")];
} else {
return [key, value.toString()];
}
}),
status: response.statusCode,
statusText: response.statusMessage,
});
});
};