You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WSO2 MI调用认证端点后转发原始multipart/form-data请求

问题解决:WSO2 MI转发multipart/form-data请求并添加认证Ticket

问题背景

需要通过WSO2 MI转发包含文件和表单字段的multipart/form-data POST请求,流程为:先调用认证接口获取Ticket,将Ticket作为请求头添加后,再转发至后端服务。原始请求示例:

curl --location --request POST 'your-endpoint' \
--header 'token: token' \
--form 'type_1="54"' \
--form 'type_2="67"' \
--form 'type_3="test"' \
--form 'file=@"///file.pdf"'

当前遇到的错误及原因

  1. CalloutMediator类型错误

    [2025-08-14 09:14:08,524] ERROR {CalloutMediator} - {api:AddDocument} The property : AUTH_PAYLOAD is not an OMElement
    

    原因:CalloutMediator要求源属性为OMElement类型,但通过enrich存储的jsonObject并非该类型,导致调用失败。

  2. 表单字段提取失败

    [2025-08-14 10:53:47,768] INFO {LogMediator} - {api:AddDocument} IN.type1 = 54, IN.type_2 = 67, IN.type_3 = test, IN.file = null
    
    Invalid datatype specified for argument "type_2"
    

    原因:XPath表达式错误,multipart/form-data请求在WSO2 MI中解析后,表单字段会存储在request作用域的属性中,而非自定义的mediate节点下;文件字段为二进制内容,无法通过text()提取。

修正后的完整序列配置

<!-- 启用流式处理,避免multipart body被提前消费 -->
<property name="ENABLE_STREAMING" value="true" scope="axis2"/>
<!-- 保存原始请求的Content-Type -->
<property name="ORIGINAL_CONTENT_TYPE" expression="get-property('transport','Content-Type')" scope="axis2" type="STRING"/>
<!-- 保存原始请求的token头 -->
<property name="ORIGINAL_TOKEN" expression="get-property('transport','token')" scope="default" type="STRING"/>

<!-- 调用认证接口获取Ticket -->
<payloadFactory media-type="json">
  <format>{"your-auth-payload-key": "your-auth-payload-value"}</format>
</payloadFactory>
<call>
  <endpoint>
    <http method="post" uri-template="your-auth-endpoint-url"/>
  </endpoint>
</call>
<!-- 提取返回的Ticket -->
<property name="AUTH_TOKEN" expression="json-eval($.ticket)" scope="default" type="STRING"/>

<!-- 恢复原始请求的body:避免流式处理导致的body丢失 -->
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
<property name="Content-Type" expression="get-property('ORIGINAL_CONTENT_TYPE')" scope="axis2"/>
<property name="messageType" expression="get-property('ORIGINAL_CONTENT_TYPE')" scope="axis2"/>

<!-- 添加认证Ticket头,恢复原始token头 -->
<header name="ticket" scope="transport" expression="get-property('AUTH_TOKEN')"/>
<header name="token" scope="transport" expression="get-property('ORIGINAL_TOKEN')"/>

<!-- 转发至后端服务 -->
<call>
  <endpoint>
    <http method="post" uri-template="your-backend-endpoint-url"/>
  </endpoint>
</call>

<log level="full"/>
<respond/>

关键修正点说明

  1. 使用Call而非Callout
    放弃CalloutMediator,改用CallMediator处理认证请求,无需手动处理属性类型问题,更适配REST风格的认证调用。

  2. 正确保存与恢复multipart请求

    • 启用ENABLE_STREAMING避免multipart body被提前消费;
    • 保存原始Content-Type和请求头,恢复时直接设置回axis2作用域,确保请求格式正确。
  3. 表单字段提取(如需修改字段时)
    如果需要修改表单字段,不要使用XPath,直接通过request作用域提取:

    <property name="type_1" expression="get-property('request:type_1')" scope="default" type="STRING"/>
    <property name="type_2" expression="get-property('request:type_2')" scope="default" type="STRING"/>
    <property name="type_3" expression="get-property('request:type_3')" scope="default" type="STRING"/>
    

    文件字段无需提取,直接转发原始multipart请求即可保证文件内容正确传输。

内容的提问来源于stack exchange,提问作者Imen Frigui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 12:44:50