2

我在配置 Mule 3.2 时遇到问题,它基本上接收 HTTP POST(multipart/form-data)并路由有效负载,然后通过 HTTP POST(multipart/form-data)发送有效负载。究竟如何在 Mule 中完成这种任务?

以下是我的部分配置

<flow name="UserBridgeFlow" doc:name="UserBridgeFlow">
    <inbound-endpoint address="http://${local.server}/${user.context}/" exchange-pattern="request-response" connector-ref="STD_HTTP_CONNECTOR" doc:name="User Endpoint"/>
    <echo-component doc:name="Echo"/>
    <transformer ref="RouteTransformer" doc:name="Transformer Reference"/>
    <response>
        <message-properties-transformer overwrite="true" doc:name="Message Properties">
            <add-message-property key="Access-Control-Allow-Origin" value="*"/>
        </message-properties-transformer>
    </response>
    <response>
        <echo-component doc:name="Echo"/>
    </response>
    <http:outbound-endpoint exchange-pattern="request-response" address="http://${user.server}/#[header:OUTBOUND:real.path]" doc:name="HTTP User"/>
    <default-exception-strategy>
        <processor-chain> 
            <logger level="INFO" doc:name="Logger"/> 
        </processor-chain>
    </default-exception-strategy>
</flow>

使用上述配置,我的二进制数据在到达另一个端点时总是损坏,并且我在浏览器(调用方端点)中收到此错误“未声明纯文本文档的字符编码。该文档将在某些文本中呈现乱码如果文档包含 US-ASCII 范围之外的字符,则浏览器配置。文件的字符编码需要在传输协议中声明或文件需要使用字节顺序标记作为编码签名。 "

-- 更新配置 --

<context:property-placeholder location="classpath:/mule.properties"/>
<custom-transformer class="id.co.zire.ebs.mule.transformer.RouteTransformer" name="RouteTransformer" doc:name="RouteTransformer"/>
<http:connector name="STD_HTTP_CONNECTOR" enableCookies="true" validateConnections="true" clientSoTimeout="20000" serverSoTimeout="10000" doc:name="HTTP\HTTPS">
    <dispatcher-threading-profile maxThreadsActive="50" maxBufferSize="150"/>
    <reconnect count="3" frequency="2000"/>
</http:connector>
<flow name="HTTPBridgeFlow" doc:name="HTTPBridgeFlow">
    <composite-source>
        <inbound-endpoint exchange-pattern="request-response" address="http://${local.server}/${user.context}/" encoding="ISO-8859-1" connector-ref="STD_HTTP_CONNECTOR" doc:name="User Endpoint"/>
        <inbound-endpoint exchange-pattern="request-response" address="http://${local.server}/${cms.context}/" encoding="ISO-8859-1" connector-ref="STD_HTTP_CONNECTOR" doc:name="CMS Endpoint"/>
        <inbound-endpoint exchange-pattern="request-response" address="http://${local.server}/${ads.context}/" encoding="ISO-8859-1" connector-ref="STD_HTTP_CONNECTOR" doc:name="Ads Endpoint"/>
    </composite-source>
    <echo-component doc:name="Echo"/>
    <transformer ref="RouteTransformer" doc:name="Transform Header"/>
    <set-property propertyName="http.method" value="#[header:INBOUND:http.method]" doc:name="Copy HTTP method"/>
    <flow-ref name="HTTPResponseFlow" doc:name="HTTP Flow Reference"/>
</flow>
<sub-flow name="HTTPResponseFlow" doc:name="HTTPResponseFlow">
    <logger message="Payload Output : #[message.payload]" level="INFO" doc:name="Logger"/>
    <choice doc:name="Choice">
        <when expression="message.inboundProperties['http.context.path'] contains '${user.context}'">
            <processor-chain>
                <http:outbound-endpoint exchange-pattern="request-response" address="http://${user.server}/#[message.inboundProperties['http.relative.path']]" responseTimeout="120000" doc:name="HTTP User"/>
            </processor-chain>
        </when>
        <when expression="message.inboundProperties['http.context.path'] contains '${cms.context}'">
            <processor-chain>
                <http:outbound-endpoint exchange-pattern="request-response" address="http://${cms.server}/#[message.inboundProperties['http.relative.path']]" responseTimeout="120000" doc:name="HTTP CMS"/>
            </processor-chain>
        </when>
        <when expression="message.inboundProperties['http.context.path'] contains '${ads.context}'">
            <processor-chain>
                <http:outbound-endpoint exchange-pattern="request-response" address="http://${ads.server}/#[message.inboundProperties['http.relative.path']]" responseTimeout="120000" doc:name="HTTP Ads"/>
            </processor-chain>
        </when>
    </choice>
    <echo-component doc:name="Echo"/>
    <message-properties-transformer doc:name="Set Cross-Domain Request Allowed">
        <add-message-property key="Access-Control-Allow-Origin" value="*"/>
        <add-message-property key="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
        <add-message-property key="Access-Control-Max-Age" value="1000"/>
        <add-message-property key="Access-Control-Allow-Headers" value="Content-Type"/>
    </message-properties-transformer>
</sub-flow>

好的,现在我已经更改了大部分配置,现在我在 HTTP POST 消息正文中传递包含的二进制数据时遇到了问题。Mule 似乎在将字节传递给出站端点之前对其进行了更改。我创建了一个自定义转换器来手动获取有效负载并解析有效负载中的二进制数据(顺便说一下,有效负载类型是字符串),但是从有效负载中检索到的二进制数据已经被更改。例如下面是十六进制原始文件字节的一部分:

ff d8 ff e0 00 10 4a 46 (ÿØÿà..JF)

但骡子转换成:

3f 3f 3f 3f 00 10 4a 46 (????..JF)

我认为是编码问题,也许 Mule 会自动将其转换为 UTF-8

-- RouteTransformer.java --

public class RouteTransformer extends AbstractMessageTransformer{
    private static final String MULE_CONFIG = "/mule.properties";
    private static final String CLIENT_IP = "MULE_REMOTE_CLIENT_ADDRESS";
    private static final String CLIENT_IP_HEADER = "Client-Ip";
    private static final String IP_REGEX = "/?((\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3}))(:(\\d{1,5}))?";
    private final String[] PASSING_HEADER;

    public RouteTransformer() throws IOException{
        Properties prop = new Properties();
        prop.load(getClass().getResourceAsStream(MULE_CONFIG));
        PASSING_HEADER = prop.getProperty("passing-header").split("\\s*,\\s*");
    }

    public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException{
        // Copy 'passing' header
        for(int i=PASSING_HEADER.length; --i>=0; ){
            String headerName = PASSING_HEADER[i];
            Object val = message.getInboundProperty(headerName);
            if(headerName.equals(CLIENT_IP)){
                String s = (String) val;
                Pattern p = Pattern.compile(IP_REGEX);
                Matcher m = p.matcher(s);
                if(!m.matches()) continue;
                else{
                    headerName = CLIENT_IP_HEADER;
                    val = m.group(1);
                }
            }
            if(val != null) message.setOutboundProperty(headerName, val);
        }

        // Routing message
        String requestString = message.getInboundProperty("http.request");
        String contextPath = message.getInboundProperty("http.context.path");
        if(requestString != null && contextPath != null)
            message.setOutboundProperty("http.real.path", requestString.substring(contextPath.length()));

        return message;
    }
}

-- 多部分/表单数据示例 --

-----------------------------20037128598723
Content-Disposition: form-data; name="name"

Angga
-----------------------------20037128598723
Content-Disposition: form-data; name="adsImage"; filename="Penguins.jpg"
Content-Type: image/jpeg

ÿØÿà..JF -- and the rest of bytes --

我希望有人可以提出一些解决方案。谢谢

4

2 回答 2

2

在您的内容类型中,您必须添加charset=utf-8

response.setContentType("application/json; charset=utf-8")

Content-Type: application/json; charset=utf-8
于 2012-11-29T11:42:26.477 回答
0

我想知道您面临的问题是否与出站 HTTP 交互中缺少内容类型(或其默认值)有关。

尝试添加一个消息属性转换器(或为阅读此内容的 3.3.x 用户添加一个复制属性消息处理器)以将“Content-Type”属性从入站范围复制到出站范围。

此外,为了严格起见,请将此端点配置为使用 POST 方法。

于 2012-08-09T14:33:23.937 回答