如何在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"'
当前遇到的错误及原因
CalloutMediator类型错误
[2025-08-14 09:14:08,524] ERROR {CalloutMediator} - {api:AddDocument} The property : AUTH_PAYLOAD is not an OMElement原因:
CalloutMediator要求源属性为OMElement类型,但通过enrich存储的jsonObject并非该类型,导致调用失败。表单字段提取失败
[2025-08-14 10:53:47,768] INFO {LogMediator} - {api:AddDocument} IN.type1 = 54, IN.type_2 = 67, IN.type_3 = test, IN.file = nullInvalid 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/>
关键修正点说明
使用Call而非Callout
放弃CalloutMediator,改用CallMediator处理认证请求,无需手动处理属性类型问题,更适配REST风格的认证调用。正确保存与恢复multipart请求
- 启用
ENABLE_STREAMING避免multipart body被提前消费; - 保存原始
Content-Type和请求头,恢复时直接设置回axis2作用域,确保请求格式正确。
- 启用
表单字段提取(如需修改字段时)
如果需要修改表单字段,不要使用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
相关产品推荐
相关产品推荐

