mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 19:59:50 +08:00
feat: support http body to new data struct
This commit is contained in:
parent
e90b055c47
commit
41f0ce1012
|
@ -1,10 +1,10 @@
|
|||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useCallback, useEffect } from 'react'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import produce from 'immer'
|
||||
import type { Body } from '../../types'
|
||||
import { BodyType } from '../../types'
|
||||
import useKeyValueList from '../../hooks/use-key-value-list'
|
||||
import { uniqueId } from 'lodash-es'
|
||||
import type { Body, BodyPayload, KeyValue as KeyValueType } from '../../types'
|
||||
import { BodyPayloadValueType, BodyType } from '../../types'
|
||||
import KeyValue from '../key-value'
|
||||
import useAvailableVarList from '../../../_base/hooks/use-available-var-list'
|
||||
import VarReferencePicker from '../../../_base/components/variable/var-reference-picker'
|
||||
|
@ -13,6 +13,8 @@ import InputWithVar from '@/app/components/workflow/nodes/_base/components/promp
|
|||
import type { ValueSelector, Var } from '@/app/components/workflow/types'
|
||||
import { VarType } from '@/app/components/workflow/types'
|
||||
|
||||
const UNIQUE_ID_PREFIX = 'key-value-'
|
||||
|
||||
type Props = {
|
||||
readonly: boolean
|
||||
nodeId: string
|
||||
|
@ -43,7 +45,15 @@ const EditBody: FC<Props> = ({
|
|||
payload,
|
||||
onChange,
|
||||
}) => {
|
||||
const { type } = payload
|
||||
const { type, data } = payload
|
||||
const bodyPayload = useMemo(() => {
|
||||
if (typeof data === 'string') { // old data
|
||||
return []
|
||||
}
|
||||
return data
|
||||
}, [data])
|
||||
const stringValue = [BodyType.formData, BodyType.xWwwFormUrlencoded].includes(type) ? '' : (bodyPayload[0]?.value || '')
|
||||
|
||||
const { availableVars, availableNodes } = useAvailableVarList(nodeId, {
|
||||
onlyLeafNodeVar: false,
|
||||
filterVar: (varPayload: Var) => {
|
||||
|
@ -55,51 +65,44 @@ const EditBody: FC<Props> = ({
|
|||
const newType = e.target.value as BodyType
|
||||
onChange({
|
||||
type: newType,
|
||||
data: '',
|
||||
data: [],
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
setBody([])
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [onChange])
|
||||
|
||||
const isCurrentKeyValue = type === BodyType.formData || type === BodyType.xWwwFormUrlencoded
|
||||
|
||||
const {
|
||||
list: body,
|
||||
setList: setBody,
|
||||
addItem: addBody,
|
||||
} = useKeyValueList(payload.data, (value) => {
|
||||
if (!isCurrentKeyValue)
|
||||
return
|
||||
|
||||
const newBody = produce(payload, (draft: Body) => {
|
||||
draft.data = value
|
||||
const handleAddBody = useCallback(() => {
|
||||
const newPayload = produce(payload, (draft) => {
|
||||
(draft.data as BodyPayload).push({
|
||||
id: uniqueId(UNIQUE_ID_PREFIX),
|
||||
type: BodyPayloadValueType.text,
|
||||
key: '',
|
||||
value: '',
|
||||
})
|
||||
})
|
||||
onChange(newBody)
|
||||
}, type === BodyType.json)
|
||||
onChange(newPayload)
|
||||
}, [onChange, payload])
|
||||
|
||||
const handleBodyPayloadChange = useCallback((newList: KeyValueType[]) => {
|
||||
const newPayload = produce(payload, (draft) => {
|
||||
draft.data = newList as BodyPayload
|
||||
})
|
||||
onChange(newPayload)
|
||||
}, [onChange, payload])
|
||||
|
||||
const filterOnlyFileVariable = (varPayload: Var) => {
|
||||
return varPayload.type === VarType.file
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isCurrentKeyValue)
|
||||
return
|
||||
|
||||
const newBody = produce(payload, (draft: Body) => {
|
||||
draft.data = body.map((item) => {
|
||||
if (!item.key && !item.value)
|
||||
return ''
|
||||
return `${item.key}:${item.value}`
|
||||
}).join('\n')
|
||||
})
|
||||
onChange(newBody)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isCurrentKeyValue])
|
||||
|
||||
const handleBodyValueChange = useCallback((value: string) => {
|
||||
const newBody = produce(payload, (draft: Body) => {
|
||||
draft.data = value
|
||||
if ((draft.data as BodyPayload).length === 0) {
|
||||
(draft.data as BodyPayload).push({
|
||||
id: uniqueId(UNIQUE_ID_PREFIX),
|
||||
type: BodyPayloadValueType.text,
|
||||
key: '',
|
||||
value: '',
|
||||
})
|
||||
}
|
||||
(draft.data as BodyPayload)[0].value = value
|
||||
})
|
||||
onChange(newBody)
|
||||
}, [onChange, payload])
|
||||
|
@ -136,9 +139,9 @@ const EditBody: FC<Props> = ({
|
|||
<KeyValue
|
||||
readonly={readonly}
|
||||
nodeId={nodeId}
|
||||
list={body}
|
||||
onChange={setBody}
|
||||
onAdd={addBody}
|
||||
list={bodyPayload as KeyValueType[]}
|
||||
onChange={handleBodyPayloadChange}
|
||||
onAdd={handleAddBody}
|
||||
isSupportFile={type === BodyType.formData}
|
||||
/>
|
||||
)}
|
||||
|
@ -148,7 +151,7 @@ const EditBody: FC<Props> = ({
|
|||
instanceId={'http-body-raw'}
|
||||
title={<div className='uppercase'>Raw text</div>}
|
||||
onChange={handleBodyValueChange}
|
||||
value={payload.data}
|
||||
value={stringValue}
|
||||
justVar
|
||||
nodesOutputVars={availableVars}
|
||||
availableNodes={availableNodes}
|
||||
|
@ -160,7 +163,7 @@ const EditBody: FC<Props> = ({
|
|||
<InputWithVar
|
||||
instanceId={'http-body-json'}
|
||||
title='JSON'
|
||||
value={payload.data}
|
||||
value={stringValue}
|
||||
onChange={handleBodyValueChange}
|
||||
justVar
|
||||
nodesOutputVars={availableVars}
|
||||
|
@ -169,6 +172,7 @@ const EditBody: FC<Props> = ({
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* TODO */}
|
||||
{type === BodyType.binary && (
|
||||
<VarReferencePicker
|
||||
nodeId={nodeId}
|
||||
|
|
|
@ -16,7 +16,7 @@ const nodeDefault: NodeDefault<HttpNodeType> = {
|
|||
params: '',
|
||||
body: {
|
||||
type: BodyType.none,
|
||||
data: '',
|
||||
data: [],
|
||||
},
|
||||
timeout: {
|
||||
max_connect_timeout: 0,
|
||||
|
|
|
@ -24,9 +24,21 @@ export type KeyValue = {
|
|||
value: string
|
||||
}
|
||||
|
||||
export enum BodyPayloadValueType {
|
||||
text = 'text',
|
||||
file = 'file',
|
||||
}
|
||||
|
||||
export type BodyPayload = {
|
||||
id?: string
|
||||
key?: string
|
||||
type: BodyPayloadValueType
|
||||
file?: ValueSelector // when type is file
|
||||
value?: string // when type is text
|
||||
}[]
|
||||
export type Body = {
|
||||
type: BodyType
|
||||
data: string
|
||||
data: string | BodyPayload // string is deprecated, it would convert to BodyPayload after loaded
|
||||
binaryFileVariable?: ValueSelector
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@ import useVarList from '../_base/hooks/use-var-list'
|
|||
import { VarType } from '../../types'
|
||||
import type { Var } from '../../types'
|
||||
import { useStore } from '../../store'
|
||||
import type { Authorization, Body, HttpNodeType, Method, Timeout } from './types'
|
||||
import { type Authorization, type Body, BodyType, type HttpNodeType, type Method, type Timeout } from './types'
|
||||
import useKeyValueList from './hooks/use-key-value-list'
|
||||
import { transformToBodyPayload } from './utils'
|
||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run'
|
||||
import {
|
||||
|
@ -28,10 +29,15 @@ const useConfig = (id: string, payload: HttpNodeType) => {
|
|||
useEffect(() => {
|
||||
const isReady = defaultConfig && Object.keys(defaultConfig).length > 0
|
||||
if (isReady) {
|
||||
setInputs({
|
||||
const newInputs = {
|
||||
...defaultConfig,
|
||||
...inputs,
|
||||
})
|
||||
}
|
||||
const bodyData = newInputs.body.data
|
||||
if (typeof bodyData === 'string')
|
||||
newInputs.body.data = transformToBodyPayload(bodyData, [BodyType.formData, BodyType.xWwwFormUrlencoded].includes(newInputs.body.type))
|
||||
|
||||
setInputs(newInputs)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultConfig])
|
||||
|
@ -127,7 +133,7 @@ const useConfig = (id: string, payload: HttpNodeType) => {
|
|||
inputs.url,
|
||||
inputs.headers,
|
||||
inputs.params,
|
||||
inputs.body.data,
|
||||
typeof inputs.body.data === 'string' ? inputs.body.data : inputs.body.data.map(item => item.value).join(''),
|
||||
])
|
||||
|
||||
const inputVarValues = (() => {
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
import type { HttpNodeType } from './types'
|
||||
import { type BodyPayload, BodyPayloadValueType } from './types'
|
||||
|
||||
export const checkNodeValid = (payload: HttpNodeType) => {
|
||||
return true
|
||||
export const transformToBodyPayload = (old: string, hasKey: boolean): BodyPayload => {
|
||||
if (!hasKey) {
|
||||
return [
|
||||
{
|
||||
type: BodyPayloadValueType.text,
|
||||
value: old,
|
||||
},
|
||||
]
|
||||
}
|
||||
const bodyPayload = old.split('\n').map((item) => {
|
||||
const [key, value] = item.split(':')
|
||||
return {
|
||||
key: key || '',
|
||||
type: BodyPayloadValueType.text,
|
||||
value: value || '',
|
||||
}
|
||||
})
|
||||
return bodyPayload
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user