diff --git a/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/AddWebhookModal.tsx b/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/AddWebhookModal.tsx index c68fc18560..366d1af355 100644 --- a/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/AddWebhookModal.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/AddWebhookModal.tsx @@ -1,6 +1,7 @@ import { triggers } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/components/HardcodedTriggers"; import { SurveyCheckboxGroup } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/components/SurveyCheckboxGroup"; import { TriggerCheckboxGroup } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/components/TriggerCheckboxGroup"; +import { validWebHookURL } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/lib/utils"; import clsx from "clsx"; import { Webhook } from "lucide-react"; import { useRouter } from "next/navigation"; @@ -42,6 +43,11 @@ export const AddWebhookModal = ({ environmentId, surveys, open, setOpen }: AddWe const handleTestEndpoint = async (sendSuccessToast: boolean) => { try { + const { valid, error } = validWebHookURL(testEndpointInput); + if (!valid) { + toast.error(error ?? "Something went wrong please try again!"); + return; + } setHittingEndpoint(true); await testEndpointAction({ url: testEndpointInput }); setHittingEndpoint(false); diff --git a/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/WebhookSettingsTab.tsx b/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/WebhookSettingsTab.tsx index d0bd643907..64bf1a4da8 100644 --- a/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/WebhookSettingsTab.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/components/WebhookSettingsTab.tsx @@ -3,6 +3,7 @@ import { triggers } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/components/HardcodedTriggers"; import { SurveyCheckboxGroup } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/components/SurveyCheckboxGroup"; import { TriggerCheckboxGroup } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/components/TriggerCheckboxGroup"; +import { validWebHookURL } from "@/app/(app)/environments/[environmentId]/integrations/webhooks/lib/utils"; import clsx from "clsx"; import { TrashIcon } from "lucide-react"; import { useRouter } from "next/navigation"; @@ -46,6 +47,11 @@ export const WebhookSettingsTab = ({ webhook, surveys, setOpen }: ActionSettings const handleTestEndpoint = async (sendSuccessToast: boolean) => { try { + const { valid, error } = validWebHookURL(testEndpointInput); + if (!valid) { + toast.error(error ?? "Something went wrong please try again!"); + return; + } setHittingEndpoint(true); await testEndpointAction({ url: testEndpointInput }); setHittingEndpoint(false); diff --git a/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/lib/utils.ts b/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/lib/utils.ts new file mode 100644 index 0000000000..c50a276b0d --- /dev/null +++ b/apps/web/app/(app)/environments/[environmentId]/integrations/webhooks/lib/utils.ts @@ -0,0 +1,37 @@ +export const validWebHookURL = (urlInput: string) => { + const trimmedInput = urlInput.trim(); + if (!trimmedInput) { + return { valid: false, error: "Please enter a URL" }; + } + + try { + const url = new URL(trimmedInput); + + if (url.protocol !== "https:") { + return { valid: false, error: "URL must start with https://" }; + } + + const domainError: string = + "Please enter a complete URL with a valid domain (e.g., https://formbricks.com)"; + + const multipleSlashesPattern = /(?