Feat: HTTP componant supports variables (#10432)

### What problem does this PR solve?

HTTP component supports variables. #10382




![http1](https://github.com/user-attachments/assets/196a2a5b-461c-455c-8896-ec2efe7c0a13)


![http2](https://github.com/user-attachments/assets/0ab97cb0-323c-456e-b556-6f416d52e59f)


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
Yongteng Lei
2025-10-09 16:05:58 +08:00
committed by GitHub
parent 2078d88c28
commit 66d0d44a00
14 changed files with 127 additions and 36 deletions

View File

@ -26,6 +26,7 @@ import { INextOperatorForm } from '../../interface';
import { buildOutputList } from '../../utils/build-output-list';
import { FormWrapper } from '../components/form-wrapper';
import { Output } from '../components/output';
import { PromptEditor } from '../components/prompt-editor';
import { FormSchema, FormSchemaType } from './schema';
import { useEditVariableRecord } from './use-edit-variable';
import { VariableDialog } from './variable-dialog';
@ -98,7 +99,13 @@ function InvokeForm({ node }: INextOperatorForm) {
<FormItem>
<FormLabel>{t('flow.url')}</FormLabel>
<FormControl>
<Input {...field} placeholder="http://" />
<PromptEditor
value={field.value}
onChange={field.onChange}
placeholder="http://"
showToolbar={false}
multiLine={false}
/>
</FormControl>
<FormMessage />
</FormItem>

View File

@ -6,8 +6,54 @@ export const VariableFormSchema = z.object({
value: z.string(),
});
// {user_id} or {component@variable}
const placeholderRegex = /\{([a-zA-Z_][a-zA-Z0-9_.@-]*)\}/g;
// URL validation schema that accepts:
// 1. Standard URLs (e.g. https://example.com/api)
// 2. URLs with variable placeholders in curly braces (e.g. https://api/{user_id}/posts)
const urlValidation = z.string().refine(
(val) => {
if (!val) return false;
const hasPlaceholders = val.includes('{') && val.includes('}');
const matches = [...val.matchAll(placeholderRegex)];
if (hasPlaceholders) {
if (
!matches.length ||
matches.some((m) => !/^[a-zA-Z_][a-zA-Z0-9_.@-]*$/.test(m[1]))
)
return false;
if ((val.match(/{/g) || []).length !== (val.match(/}/g) || []).length)
return false;
const testURL = val.replace(placeholderRegex, 'placeholder');
return isValidURL(testURL);
}
return isValidURL(val);
},
{
message: 'Must be a valid URL or URL with variable placeholders',
},
);
function isValidURL(str: string): boolean {
try {
// Try to construct a full URL; prepend http:// if protocol is missing
new URL(str.startsWith('http') ? str : `http://${str}`);
return true;
} catch {
// Allow relative paths (e.g. /api/users) if needed
return /^\/[a-zA-Z0-9]/.test(str);
}
}
export const FormSchema = z.object({
url: z.string().url(),
url: urlValidation,
method: z.string(),
timeout: z.number(),
headers: z.string(),