From bc2edf510762c6fd3e78216b65b1b267c0d9f385 Mon Sep 17 00:00:00 2001 From: zhsama Date: Wed, 22 Oct 2025 14:55:57 +0800 Subject: [PATCH] refactor(workflow): replace fetch function with base/post in use-one-step-run and use-workflow-run hooks in polling --- .../workflow-app/hooks/use-workflow-run.ts | 41 +++++++----- .../nodes/_base/hooks/use-one-step-run.ts | 62 ++++++------------- 2 files changed, 43 insertions(+), 60 deletions(-) diff --git a/web/app/components/workflow-app/hooks/use-workflow-run.ts b/web/app/components/workflow-app/hooks/use-workflow-run.ts index 3c58dccf55..cf79ffcc49 100644 --- a/web/app/components/workflow-app/hooks/use-workflow-run.ts +++ b/web/app/components/workflow-app/hooks/use-workflow-run.ts @@ -23,8 +23,8 @@ import { useNodesSyncDraft } from './use-nodes-sync-draft' import { useInvalidAllLastRun } from '@/service/use-workflow' import { useSetWorkflowVarsWithValue } from '../../workflow/hooks/use-fetch-workflow-inspect-vars' import { useConfigsMap } from './use-configs-map' -import { API_PREFIX } from '@/config' -import { base } from '@/service/fetch' +import { post } from '@/service/base' +import { ContentType } from '@/service/fetch' import { TriggerType } from '@/app/components/workflow/header/test-run-menu' import { AppModeEnum } from '@/types/app' @@ -464,10 +464,6 @@ export const useWorkflowRun = () => { }) const runTriggerDebug = async (debugType: TriggerType.Webhook | TriggerType.Plugin | TriggerType.All) => { - const urlWithPrefix = (url.startsWith('http://') || url.startsWith('https://')) - ? url - : `${API_PREFIX}${url.startsWith('/') ? url : `/${url}`}` - const controller = new AbortController() abortControllerRef.current = controller @@ -481,29 +477,42 @@ export const useWorkflowRun = () => { const poll = async (): Promise => { try { - const response = await base(urlWithPrefix, { - method: 'POST', - body: JSON.stringify(requestBody), + const response = await post(url, { + body: requestBody, signal: controller.signal, + }, { + needAllResponseContent: true, }) if (controller.signal.aborted) return - if (!response.ok) { - const message = `${debugLabel} debug request failed (${response.status})` + if (!response) { + const message = `${debugLabel} debug request failed` Toast.notify({ type: 'error', message }) clearAbortController() return } - const contentType = response.headers.get('Content-Type')?.toLowerCase() || '' - if (contentType.includes('application/json')) { - const data = await response.json() + const contentType = response.headers.get('content-type') || '' + + if (contentType.includes(ContentType.json)) { + let data: any = null + try { + data = await response.json() + } + catch (jsonError) { + console.error(`handleRun: ${debugLabel.toLowerCase()} debug response parse error`, jsonError) + Toast.notify({ type: 'error', message: `${debugLabel} debug request failed` }) + clearAbortController() + clearListeningState() + return + } + if (controller.signal.aborted) return - if (data.status === 'waiting') { + if (data?.status === 'waiting') { const delay = Number(data.retry_in) || 2000 await waitWithAbort(controller.signal, delay) if (controller.signal.aborted) @@ -512,7 +521,7 @@ export const useWorkflowRun = () => { return } - const errorMessage = data.message || `${debugLabel} debug failed` + const errorMessage = data?.message || `${debugLabel} debug failed` Toast.notify({ type: 'error', message: errorMessage }) clearAbortController() setWorkflowRunningData({ diff --git a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts index 9075981ae7..d7bac6d3ca 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts @@ -28,7 +28,7 @@ import ParameterExtractorDefault from '@/app/components/workflow/nodes/parameter import IterationDefault from '@/app/components/workflow/nodes/iteration/default' import DocumentExtractorDefault from '@/app/components/workflow/nodes/document-extractor/default' import LoopDefault from '@/app/components/workflow/nodes/loop/default' -import { ssePost } from '@/service/base' +import { post, ssePost } from '@/service/base' import { noop } from 'lodash-es' import { getInputVars as doGetInputVars } from '@/app/components/base/prompt-editor/constants' import type { NodeRunResult, NodeTracing } from '@/types/workflow' @@ -53,9 +53,6 @@ import { useInvalidLastRun } from '@/service/use-workflow' import useInspectVarsCrud from '../../../hooks/use-inspect-vars-crud' import type { FlowType } from '@/types/common' import useMatchSchemaType from '../components/variable/use-match-schema-type' -import Cookies from 'js-cookie' -import { API_PREFIX, CSRF_COOKIE_NAME, CSRF_HEADER_NAME } from '@/config' -import { getBaseOptions } from '@/service/fetch' // eslint-disable-next-line ts/no-unsafe-function-type const checkValidFns: Record = { [BlockEnum.LLM]: checkLLMValid, @@ -287,7 +284,6 @@ const useOneStepRun = ({ const runWebhookSingleRun = useCallback(async (): Promise => { const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run` - const urlWithPrefix = `${API_PREFIX}${urlPath.startsWith('/') ? urlPath : `/${urlPath}`}` webhookSingleRunActiveRef.current = true const token = ++webhookSingleRunTokenRef.current @@ -297,15 +293,7 @@ const useOneStepRun = ({ webhookSingleRunAbortRef.current = controller try { - const baseOptions = getBaseOptions() - const headers = new Headers(baseOptions.headers as Headers) - headers.set('Content-Type', 'application/json') - headers.set(CSRF_HEADER_NAME, Cookies.get(CSRF_COOKIE_NAME()) || '') - - const response = await fetch(urlWithPrefix, { - ...baseOptions, - method: 'POST', - headers, + const response: any = await post(urlPath, { body: JSON.stringify({}), signal: controller.signal, }) @@ -313,18 +301,15 @@ const useOneStepRun = ({ if (!webhookSingleRunActiveRef.current || token !== webhookSingleRunTokenRef.current) return null - const contentType = response.headers.get('Content-Type')?.toLowerCase() || '' - const responseData = contentType.includes('application/json') ? await response.json() : undefined - - if (!response.ok) { - const message = responseData?.message || 'Webhook debug failed' + if (!response) { + const message = response?.message || 'Webhook debug failed' Toast.notify({ type: 'error', message }) cancelWebhookSingleRun() throw new Error(message) } - if (responseData?.status === 'waiting') { - const delay = Number(responseData.retry_in) || 2000 + if (response?.status === 'waiting') { + const delay = Number(response.retry_in) || 2000 webhookSingleRunAbortRef.current = null if (!webhookSingleRunActiveRef.current || token !== webhookSingleRunTokenRef.current) return null @@ -344,8 +329,8 @@ const useOneStepRun = ({ continue } - if (responseData?.status === 'error') { - const message = responseData.message || 'Webhook debug failed' + if (response?.status === 'error') { + const message = response.message || 'Webhook debug failed' Toast.notify({ type: 'error', message }) cancelWebhookSingleRun() throw new Error(message) @@ -361,7 +346,7 @@ const useOneStepRun = ({ }) cancelWebhookSingleRun() - return responseData + return response } catch (error) { if (controller.signal.aborted && (!webhookSingleRunActiveRef.current || token !== webhookSingleRunTokenRef.current)) @@ -386,7 +371,6 @@ const useOneStepRun = ({ const runPluginSingleRun = useCallback(async (): Promise => { const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run` - const urlWithPrefix = `${API_PREFIX}${urlPath.startsWith('/') ? urlPath : `/${urlPath}`}` pluginSingleRunActiveRef.current = true const token = ++pluginSingleRunTokenRef.current @@ -396,33 +380,23 @@ const useOneStepRun = ({ pluginSingleRunAbortRef.current = controller try { - const baseOptions = getBaseOptions() - const headers = new Headers(baseOptions.headers as Headers) - headers.set('Content-Type', 'application/json') - headers.set(CSRF_HEADER_NAME, Cookies.get(CSRF_COOKIE_NAME()) || '') - - const response = await fetch(urlWithPrefix, { - ...baseOptions, - method: 'POST', - headers, + const response: any = await post(urlPath, { + body: JSON.stringify({}), signal: controller.signal, }) if (!pluginSingleRunActiveRef.current || token !== pluginSingleRunTokenRef.current) return null - const contentType = response.headers.get('Content-Type')?.toLowerCase() || '' - const responseData = contentType.includes('application/json') ? await response.json() : undefined - - if (!response.ok) { - const message = responseData?.message || 'Plugin debug failed' + if (!response) { + const message = response?.message || 'Plugin debug failed' Toast.notify({ type: 'error', message }) cancelPluginSingleRun() throw new Error(message) } - if (responseData?.status === 'waiting') { - const delay = Number(responseData.retry_in) || 2000 + if (response?.status === 'waiting') { + const delay = Number(response.retry_in) || 2000 pluginSingleRunAbortRef.current = null if (!pluginSingleRunActiveRef.current || token !== pluginSingleRunTokenRef.current) return null @@ -442,8 +416,8 @@ const useOneStepRun = ({ continue } - if (responseData?.status === 'error') { - const message = responseData.message || 'Plugin debug failed' + if (response?.status === 'error') { + const message = response.message || 'Plugin debug failed' Toast.notify({ type: 'error', message }) cancelPluginSingleRun() throw new Error(message) @@ -459,7 +433,7 @@ const useOneStepRun = ({ }) cancelPluginSingleRun() - return responseData + return response } catch (error) { if (controller.signal.aborted && (!pluginSingleRunActiveRef.current || token !== pluginSingleRunTokenRef.current))