mirror of https://github.com/langgenius/dify.git
chore: (trigger)change content type from form to application/octet-stream (#25167)
This commit is contained in:
parent
eab03e63d4
commit
d8f6f9ce19
|
|
@ -21,7 +21,7 @@ class ContentType(StrEnum):
|
|||
FORM_DATA = "multipart/form-data"
|
||||
FORM_URLENCODED = "application/x-www-form-urlencoded"
|
||||
TEXT = "text/plain"
|
||||
FORM = "form"
|
||||
BINARY = "application/octet-stream"
|
||||
|
||||
|
||||
class WebhookParameter(BaseModel):
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ class TriggerWebhookNode(BaseNode):
|
|||
# For text/plain, the entire body is a single string parameter
|
||||
outputs[param_name] = str(webhook_data.get("body", {}).get("raw", ""))
|
||||
continue
|
||||
elif self._node_data.content_type == ContentType.BINARY:
|
||||
outputs[param_name] = webhook_data.get("body", {}).get("raw", b"")
|
||||
continue
|
||||
|
||||
if param_type == "file":
|
||||
# Get File object (already processed by webhook controller)
|
||||
|
|
|
|||
|
|
@ -97,12 +97,45 @@ class WebhookService:
|
|||
# Handle file uploads
|
||||
if request.files:
|
||||
data["files"] = cls._process_file_uploads(request.files, webhook_trigger)
|
||||
else:
|
||||
# Raw text data
|
||||
elif "application/octet-stream" in content_type:
|
||||
# Binary data - process as file using ToolFileManager
|
||||
try:
|
||||
file_content = request.get_data()
|
||||
if file_content:
|
||||
tool_file_manager = ToolFileManager()
|
||||
|
||||
# Create file using ToolFileManager
|
||||
tool_file = tool_file_manager.create_file_by_raw(
|
||||
user_id=webhook_trigger.created_by,
|
||||
tenant_id=webhook_trigger.tenant_id,
|
||||
conversation_id=None,
|
||||
file_binary=file_content,
|
||||
mimetype="application/octet-stream",
|
||||
)
|
||||
|
||||
# Build File object
|
||||
mapping = {
|
||||
"tool_file_id": tool_file.id,
|
||||
"transfer_method": FileTransferMethod.TOOL_FILE.value,
|
||||
}
|
||||
file_obj = file_factory.build_from_mapping(
|
||||
mapping=mapping,
|
||||
tenant_id=webhook_trigger.tenant_id,
|
||||
)
|
||||
data["body"] = {"raw": file_obj.to_dict()}
|
||||
else:
|
||||
data["body"] = {"raw": None}
|
||||
except Exception:
|
||||
logger.exception("Failed to process octet-stream data")
|
||||
data["body"] = {"raw": None}
|
||||
elif "text/plain" in content_type:
|
||||
# Text data - store as raw string
|
||||
try:
|
||||
data["body"] = {"raw": request.get_data(as_text=True)}
|
||||
except Exception:
|
||||
data["body"] = {"raw": ""}
|
||||
else:
|
||||
raise ValueError(f"Unsupported Content-Type: {content_type}")
|
||||
|
||||
return data
|
||||
|
||||
|
|
@ -275,25 +308,7 @@ class WebhookService:
|
|||
return validation_result
|
||||
|
||||
else:
|
||||
# For other unsupported content types, only validate existence of required parameters
|
||||
body_params = node_data.get("body", [])
|
||||
for body_param in body_params:
|
||||
param_name = body_param.get("name", "")
|
||||
param_type = body_param.get("type", SegmentType.STRING)
|
||||
is_required = body_param.get("required", False)
|
||||
|
||||
if not is_required:
|
||||
continue
|
||||
|
||||
# Check if parameter exists
|
||||
if param_type == SegmentType.FILE:
|
||||
file_obj = webhook_data.get("files", {}).get(param_name)
|
||||
if not file_obj:
|
||||
return {"valid": False, "error": f"Required file parameter missing: {param_name}"}
|
||||
else:
|
||||
body_data = webhook_data.get("body", {})
|
||||
if param_name not in body_data:
|
||||
return {"valid": False, "error": f"Required body parameter missing: {param_name}"}
|
||||
raise ValueError(f"Unsupported Content-Type for validation: {configured_content_type}")
|
||||
|
||||
return {"valid": True}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,17 +78,19 @@ const ParameterTable: FC<ParameterTableProps> = ({
|
|||
|
||||
const handleDataChange = (data: GenericTableRow[]) => {
|
||||
// For text/plain, enforce single text body semantics: keep only first non-empty row and force string type
|
||||
// For application/octet-stream, enforce single file body semantics: keep only first non-empty row and force file type
|
||||
const isTextPlain = isRequestBody && (contentType || '').toLowerCase() === 'text/plain'
|
||||
const isOctetStream = isRequestBody && (contentType || '').toLowerCase() === 'application/octet-stream'
|
||||
|
||||
const normalized = data
|
||||
.filter(row => typeof row.key === 'string' && (row.key as string).trim() !== '')
|
||||
.map(row => ({
|
||||
name: String(row.key),
|
||||
type: isTextPlain ? VarType.string : normalizeParameterType((row.type as string)),
|
||||
type: isTextPlain ? VarType.string : isOctetStream ? VarType.file : normalizeParameterType((row.type as string)),
|
||||
required: Boolean(row.required),
|
||||
}))
|
||||
|
||||
const newParams: WebhookParameter[] = isTextPlain
|
||||
const newParams: WebhookParameter[] = (isTextPlain || isOctetStream)
|
||||
? normalized.slice(0, 1)
|
||||
: normalized
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const CONTENT_TYPES = [
|
|||
{ name: 'application/json', value: 'application/json' },
|
||||
{ name: 'application/x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' },
|
||||
{ name: 'text/plain', value: 'text/plain' },
|
||||
{ name: 'forms', value: 'forms' },
|
||||
{ name: 'application/octet-stream', value: 'application/octet-stream' },
|
||||
{ name: 'multipart/form-data', value: 'multipart/form-data' },
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ const CONTENT_TYPE_CONFIGS = {
|
|||
supportedTypes: [VarType.string, VarType.number, VarType.boolean] as const,
|
||||
description: 'Form data supports basic types',
|
||||
},
|
||||
'forms': {
|
||||
supportedTypes: [VarType.string, VarType.number, VarType.boolean] as const,
|
||||
description: 'Form data supports basic types',
|
||||
'application/octet-stream': {
|
||||
supportedTypes: [VarType.file] as const,
|
||||
description: 'octet-stream supports only binary data',
|
||||
},
|
||||
'multipart/form-data': {
|
||||
supportedTypes: [VarType.string, VarType.number, VarType.boolean, VarType.file] as const,
|
||||
|
|
|
|||
Loading…
Reference in New Issue