use original request sources for endpoint conditions

This commit is contained in:
fawney19
2026-05-06 23:48:31 +08:00
parent e2bffbbaca
commit 4e9f063385
31 changed files with 524 additions and 135 deletions

View File

@@ -140,7 +140,7 @@ export interface BodyRuleConditionLeaf {
path: string
op: BodyRuleConditionOp
value?: unknown // exists / not_exists 不需要 value
source?: 'original' | 'current'
source?: 'request_headers' // 不填表示请求体;填 request_headers 表示请求头
}
export interface BodyRuleConditionAll {

View File

@@ -127,17 +127,17 @@
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="current">
Current
<SelectItem value="body">
请求体
</SelectItem>
<SelectItem value="original">
Original
<SelectItem value="request_headers">
请求头
</SelectItem>
</SelectContent>
</Select>
<Input
:model-value="modelValue.path"
:placeholder="pathHint || '字段路径'"
:placeholder="modelValue.source === 'request_headers' ? 'Header 名称' : (pathHint || '字段路径')"
size="sm"
class="flex-1 min-w-[120px] h-7 text-xs"
@update:model-value="(value) => updateLeafField('path', value)"

View File

@@ -635,14 +635,14 @@
<code>in</code> 在列表中(值填 <code>["a","b"]</code><br>
<code>type_is</code> 类型判断string/number/boolean/array/object/null<br>
条件路径支持 <code>$item.xxx</code> 引用通配符当前元素<br>
可切换 <code>Current</code>/<code>Original</code> 数据源,并支持 <code>ALL</code>/<code>ANY</code> 组合条件
可切换 <code>请求体</code>/<code>请求头</code> 数据源,并支持 <code>ALL</code>/<code>ANY</code> 组合条件
</div>
</div>
<div class="text-muted-foreground">
规则按顺序执行,前面的修改对后续规则可见
规则按顺序执行;条件判断使用客户端原始请求体或原始请求头,不受前面规则修改影响
</div>
<div class="text-muted-foreground">
规则默认在格式转换后按目标提供商结构匹配;条件切到 <code>Original</code> 时按客户端原始请求匹配。
条件默认按客户端原始请求体匹配;切到 <code>请求头</code> 时按客户端原始请求匹配。
</div>
</div>
</PopoverContent>
@@ -1484,8 +1484,8 @@ function validateJsonConditionShape(condition: Record<string, unknown>, label: s
if (typeof condition.op !== 'string' || !CONDITION_JSON_OPS.has(condition.op)) {
return `${label}.op 无效`
}
if (condition.source !== undefined && condition.source !== 'original' && condition.source !== 'current') {
return `${label}.source 只能是 original/current`
if (condition.source !== undefined && condition.source !== 'request_headers') {
return `${label}.source 只能是 request_headers请求体条件不要填写 source`
}
return null
}

View File

@@ -1,6 +1,6 @@
import type { BodyRuleCondition, BodyRuleConditionOp } from '@/api/endpoints'
export type ConditionSource = 'current' | 'original'
export type ConditionSource = 'body' | 'request_headers'
export type ConditionGroupMode = 'all' | 'any'
export interface EditableConditionLeaf {
@@ -46,7 +46,7 @@ export function createEmptyConditionLeaf(): EditableConditionLeaf {
path: '',
op: 'eq',
value: '',
source: 'current',
source: 'body',
}
}
@@ -86,6 +86,7 @@ export function conditionToEditable(condition?: BodyRuleCondition | null): Edita
condition.any.map(child => conditionToEditable(child) || createEmptyConditionLeaf()),
)
}
const source = (condition as { source?: unknown }).source
return {
kind: 'leaf',
path: condition.path || '',
@@ -93,7 +94,9 @@ export function conditionToEditable(condition?: BodyRuleCondition | null): Edita
value: condition.value !== undefined
? (typeof condition.value === 'string' ? condition.value : JSON.stringify(condition.value))
: '',
source: condition.source === 'original' ? 'original' : 'current',
source: source === 'request_headers' || source === 'headers'
? 'request_headers'
: 'body',
}
}
@@ -114,7 +117,7 @@ export function editableConditionToApi(node: EditableConditionNode | null): Body
const base = {
path,
op: node.op,
...(node.source === 'original' ? { source: 'original' as const } : {}),
...(node.source === 'request_headers' ? { source: 'request_headers' as const } : {}),
}
if (node.op === 'exists' || node.op === 'not_exists') {