diff --git a/server/src/service/network/AdvancedMatcher.ts b/server/src/service/network/AdvancedMatcher.ts index 8b25c53e8..8e77ef3ec 100644 --- a/server/src/service/network/AdvancedMatcher.ts +++ b/server/src/service/network/AdvancedMatcher.ts @@ -1,5 +1,6 @@ import { Monitor } from "@/domain/monitors/monitor.types.js"; import jmespath from "jmespath"; +import RE2 from "re2"; type JmesPath = typeof jmespath; export interface IAdvancedMatcher { @@ -9,13 +10,6 @@ export interface IAdvancedMatcher { export class AdvancedMatcher implements IAdvancedMatcher { constructor(private jmespath: JmesPath) {} - private compare(actual: unknown, expected: string, method?: string): boolean { - if (method === "equal") return String(actual) === expected; - if (method === "include") return String(actual).includes(expected); - if (method === "regex") return new RegExp(expected).test(String(actual)); - return String(actual) === expected; // Default - } - validate(payload: T, monitor: Monitor): { ok: boolean; message: string; extracted?: T | undefined } { const { useAdvancedMatching, jsonPath, matchMethod, expectedValue } = monitor; if (!useAdvancedMatching) return { ok: true, message: "Success" }; @@ -30,19 +24,38 @@ export class AdvancedMatcher implements IAdvancedMatcher { } } - if (expectedValue) { - const ok = this.compare(dataToValidate, expectedValue, matchMethod); + if (!expectedValue) { + const isFalsy = dataToValidate === false || dataToValidate === "false" || dataToValidate === undefined || dataToValidate === null; return { - ok, - message: ok ? "Success" : "Expected value did not match", + ok: !isFalsy, + message: !isFalsy ? "Success" : "Extracted value is falsy", extracted: dataToValidate, }; } - const isFalsy = dataToValidate === false || dataToValidate === "false" || dataToValidate === undefined || dataToValidate === null; + let actual: string; + try { + actual = String(dataToValidate); + } catch { + return { ok: false, message: "Error evaluating response value", extracted: dataToValidate }; + } + + let ok: boolean; + if (matchMethod === "include") { + ok = actual.includes(expectedValue); + } else if (matchMethod === "regex") { + try { + ok = new RE2(expectedValue).test(actual); + } catch { + return { ok: false, message: "Invalid regex pattern", extracted: dataToValidate }; + } + } else { + ok = actual === expectedValue; + } + return { - ok: !isFalsy, - message: !isFalsy ? "Success" : "Extracted value is falsy", + ok, + message: ok ? "Success" : "Expected value did not match", extracted: dataToValidate, }; }