From 642c6f0d72b7bf4f47adf1e9b04fff09dd457e38 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Mon, 27 Sep 2021 19:45:37 +0300 Subject: [PATCH] Detect log follow requests (#3890) * detect log follow requests Signed-off-by: Jari Kolehmainen * fix Signed-off-by: Jari Kolehmainen * refactor to use getBoolean Signed-off-by: Jari Kolehmainen * refactor to use getBoolean Signed-off-by: Jari Kolehmainen * refactor to use getBoolean Signed-off-by: Jari Kolehmainen --- .../index.ts => __test__/lens-proxy.test.ts} | 37 ++++++++++++++++++- src/main/context-handler.ts | 6 +-- src/main/lens-proxy.ts | 13 ++++++- src/main/routes/helm-route.ts | 2 +- src/main/{routes => }/utils/parse-query.ts | 0 5 files changed, 51 insertions(+), 7 deletions(-) rename src/main/{routes/utils/index.ts => __test__/lens-proxy.test.ts} (52%) rename src/main/{routes => }/utils/parse-query.ts (100%) diff --git a/src/main/routes/utils/index.ts b/src/main/__test__/lens-proxy.test.ts similarity index 52% rename from src/main/routes/utils/index.ts rename to src/main/__test__/lens-proxy.test.ts index 4a7de80225..f7767fc685 100644 --- a/src/main/routes/utils/index.ts +++ b/src/main/__test__/lens-proxy.test.ts @@ -18,4 +18,39 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -export * from "./parse-query"; + +import { isLongRunningRequest } from "../lens-proxy"; + +describe("isLongRunningRequest", () => { + it("returns true on watches", () => { + ["watch=true", "watch=1", "watch"].forEach((param) => { + expect( + isLongRunningRequest(`/api/v1/namespaces/default/pods?${param}`) + ).toBeTruthy(); + }); + }); + + it("returns false on disabled watches", () => { + ["watch=false", "watch=0", ""].forEach((param) => { + expect( + isLongRunningRequest(`/api/v1/namespaces/default/pods?${param}`) + ).toBeFalsy(); + }); + }); + + it("returns true on follows", () => { + ["follow=true", "follow=1", "follow"].forEach((param) => { + expect( + isLongRunningRequest(`/api/v1/namespaces/default/pods/foo/log?${param}`) + ).toBeTruthy(); + }); + }); + + it("returns false on disabled follows", () => { + ["follow=false", "follow=0", ""].forEach((param) => { + expect( + isLongRunningRequest(`/api/v1/namespaces/default/pods/foo/log?${param}`) + ).toBeFalsy(); + }); + }); +}); diff --git a/src/main/context-handler.ts b/src/main/context-handler.ts index 82c365e821..b6e14df4e5 100644 --- a/src/main/context-handler.ts +++ b/src/main/context-handler.ts @@ -117,10 +117,10 @@ export class ContextHandler { return `http://127.0.0.1:${this.kubeAuthProxy.port}${path}`; } - async getApiTarget(isWatchRequest = false): Promise { - const timeout = isWatchRequest ? 4 * 60 * 60 * 1000 : 30000; // 4 hours for watch request, 30 seconds for the rest + async getApiTarget(isLongRunningRequest = false): Promise { + const timeout = isLongRunningRequest ? 4 * 60 * 60_000 : 30_000; // 4 hours for long running request, 30 seconds for the rest - if (isWatchRequest) { + if (isLongRunningRequest) { return this.newApiTarget(timeout); } diff --git a/src/main/lens-proxy.ts b/src/main/lens-proxy.ts index 3cd5182677..47f4c4756f 100644 --- a/src/main/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -31,6 +31,7 @@ import { Singleton } from "../common/utils"; import type { Cluster } from "./cluster"; import type { ProxyApiRequestArgs } from "./proxy-functions"; import { appEventBus } from "../common/event-bus"; +import { getBoolean } from "./utils/parse-query"; type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | null; @@ -40,6 +41,15 @@ export interface LensProxyFunctions { kubeApiRequest: (args: ProxyApiRequestArgs) => void | Promise; } +const watchParam = "watch"; +const followParam = "follow"; + +export function isLongRunningRequest(reqUrl: string) { + const url = new URL(reqUrl, "http://localhost"); + + return getBoolean(url.searchParams, watchParam) || getBoolean(url.searchParams, followParam); +} + export class LensProxy extends Singleton { protected origin: string; protected proxyServer: http.Server; @@ -174,9 +184,8 @@ export class LensProxy extends Singleton { if (req.url.startsWith(apiKubePrefix)) { delete req.headers.authorization; req.url = req.url.replace(apiKubePrefix, ""); - const isWatchRequest = req.url.includes("watch="); - return contextHandler.getApiTarget(isWatchRequest); + return contextHandler.getApiTarget(isLongRunningRequest(req.url)); } } diff --git a/src/main/routes/helm-route.ts b/src/main/routes/helm-route.ts index 5e104f6a11..2f217a3193 100644 --- a/src/main/routes/helm-route.ts +++ b/src/main/routes/helm-route.ts @@ -23,7 +23,7 @@ import type { LensApiRequest } from "../router"; import { helmService } from "../helm/helm-service"; import logger from "../logger"; import { respondJson, respondText } from "../utils/http-responses"; -import { getBoolean } from "./utils/parse-query"; +import { getBoolean } from "../utils/parse-query"; export class HelmApiRoute { static async listCharts(request: LensApiRequest) { diff --git a/src/main/routes/utils/parse-query.ts b/src/main/utils/parse-query.ts similarity index 100% rename from src/main/routes/utils/parse-query.ts rename to src/main/utils/parse-query.ts