receiving and sending multipart/form-data in mule 3.2 - http

I have problem in configuring Mule 3.2 which basically receive HTTP POST (multipart/form-data) and routing the payload and then send the payload by HTTP POST (multipart/form-data). How exactly to do that kind of task in Mule ?
Below are parts of my configuration
<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>
With above configuration, my binary data is always corrupted when reaching the other endpoint and also I get this error in the browser (caller endpoint) "The character encoding of the plain text document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the file needs to be declared in the transfer protocol or file needs to use a byte order mark as an encoding signature."
-- UPDATED CONFIGURATION --
<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>
OK, now I have change most of the configuration, now I have problem of passing the included binary data in the HTTP POST message body. Mule seems to be altering the bytes before passing it to the outbound endpoint. I have create a custom transformer to get the payload manually and parse the binary data from the payload (payload type is String by the way) but the retrieved binary data from payload is already altered. For example below is part of the original file bytes in hexadecimal:
ff d8 ff e0 00 10 4a 46 (ÿØÿà..JF)
but Mule converts into:
3f 3f 3f 3f 00 10 4a 46 (????..JF)
I think it is encoding issue, maybe Mule converts it automatically to 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;
}
}
-- Multipart/form-data example --
-----------------------------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 --
I hope somebody can bring some solutions.
Thanks

In your content type you have to add charset=utf-8:
response.setContentType("application/json; charset=utf-8")
Content-Type: application/json; charset=utf-8

I'm wondering if the issue you're facing is related to the lack of content type (or its default value) on the outbound HTTP interaction.
Try adding a message properties transformer (or a copy properties message processor for 3.3.x users reading this) to copy the "Content-Type" property from the inbound scope to the outbound one.
Also, for strictness' sake, configure this endpoint to use the POST method.

Related

Mule ESB conditional Exchange pattern for UDP/TCP transport

I need to send an acknowledge response for some messages went an acknowledge needed flag is set for that purpose.
Using a Java component I build a Payload string array with this structure:
Payload[0]=message entry.
Payload[1]="true"/"false" // This is the acknowledge needed flag.
Payload[2]="OK"/"ON"/"OFF"// Response to the transport (went flag="true")
This is my XML code
<tcp:connector name="TCP" validateConnections="false" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" keepAlive="true" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" doc:name="TCP">
<tcp:direct-protocol rethrowExceptionOnRead="true" payloadOnly="true"/>
</tcp:connector>
<flow name="verifyFlow">
<tcp:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9446" connector-ref="TCP" responseTimeout="10000" doc:name="TCP" transformer-refs="Byte_Array_to_String"/>
<component class="verify.as" doc:name="Java Component"/>
<choice doc:name="Choice">
<when expression="#[message.payload[1] == 'false']">
<set-payload value="""" doc:name="No response"/>
</when>
<otherwise>
<expression-transformer mimeType="text/plain" expression="#[message.payload[2]]" doc:name="Expression"/>
</otherwise>
</choice>
</flow>
The problem I'm facing is that went ever the flag is "false" there shouldn't be any response send to the transport (no 'null' value, no empty string, no "", Etc.) ¿Is there any way to change the exchange pattern of the TCP (or UDP) connector from request-response to one way inside the flow?

mule restful proxy throws null pointer exception

i am building a simple restful proxy using mule. while majority of the rest calls are proxied properly, one of the POST call is throwing a null pointer exception.
Here's the message inbound:
org.mule.DefaultMuleMessage
{
id=c856d080-bd55-11e4-8504-6c40089d7cb6
payload=java.lang.String
correlationId=<not set>
correlationGroup=-1
correlationSeq=-1
encoding=UTF-8
exceptionPayload=<not set>
Message properties:
INVOCATION scoped properties:
INBOUND scoped properties:
accept=text/virl+xml,multipart/mixed
authorization=Basic TmV0U2ltOk5ldFNpbQ==
connection=keep-alive
content-length=1000
content-type=application/xml
host=localhost:9090
http.listener.path=/*
http.method=POST
http.query.params=org.mule.module.http.internal.ParameterMap#330eee18
http.query.string=session=0c603343-49e6-452f-bfdf-1e69cf478f65
http.remote.address=/127.0.0.1:52065
http.request.path=/ank/rest/process
http.request.uri=/ank/rest/process?session=0c603343-49e6-452f-bfdf-1e69cf478f65
http.scheme=http
http.uri.params=org.mule.module.http.internal.ParameterMap#0
http.version=HTTP/1.1
user-agent=Jersey/2.0-rc1 (HttpUrlConnection 1.7.0_71)
OUTBOUND scoped properties:
Content-Type=text/plain;charset=UTF-8
MULE_ENCODING=UTF-8
http.disable.status.code.exception.check=false
SESSION scoped properties:
}
ERROR 2015-02-25 19:21:26,894 [[restproxy].VIRL-UWM-Management-APIs.worker.02] org.mule.exception.CatchMessagingExceptionStrategy:
********************************************************************************
Message : null (java.lang.NullPointerException). Message payload is of type: String
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. null (java.lang.NullPointerException)
org.mule.module.http.internal.HttpParser:94 (null)
2. null (java.lang.NullPointerException). Message payload is of type: String (org.mule.api.MessagingException)
org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:32 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
java.lang.NullPointerException
at org.mule.module.http.internal.HttpParser.parseMultipartContent(HttpParser.java:94)
at org.mule.module.http.internal.request.HttpResponseToMuleEvent.getInboundAttachments(HttpResponseToMuleEvent.java:139)
at org.mule.module.http.internal.request.HttpResponseToMuleEvent.convert(HttpResponseToMuleEvent.java:77)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
Have no clue why is it failing. Hitting the actual end point by-passing the proxy works properly. any clues ?
Mule flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.6.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<http:listener-config name="VIRL-UWM-Management-APIs" host="0.0.0.0" port="9090" doc:name="HTTP Listener Configuration"/>
<http:request-config name="Actual-Virl-Enpoint-for-UWM" host="virl03.stic.cisco-services.com" port="19399" doc:name="HTTP Request Configuration"/>
<http:listener-config name="AutoNetKit-API" host="0.0.0.0" port="19401" doc:name="HTTP Listener Configuration"/>
<http:request-config name="AutoNetkit-End-Point" host="virl03.stic.cisco-services.com" port="19401" doc:name="HTTP Request Configuration"/>
<flow name="virl-proxyFlow">
<http:listener config-ref="AutoNetKit-API" path="*" allowedMethods="GET" doc:name="HTTP"/>
<set-property propertyName="http.disable.status.code.exception.check" value="false" doc:name="Disable Exception Check"/>
<logger message=" payload is: #[message.payload], method is: #[message.inboundProperties.'http.method'], Request URI is: #[message.inboundProperties.'http.request.uri'], message is: #[message]" level="INFO" doc:name="Logger"/>
<flow-ref name="copy-headers" doc:name="Copy HTTP Headers"/>
<http:request config-ref="AutoNetkit-End-Point" path="#[message.inboundProperties.'http.request.uri']" method="#[message.inboundProperties.'http.method']" responseTimeout="60000" doc:name="AutoNetKit-EndPoint"/>
<flow-ref name="copy-headers" doc:name="Copy HTTP Headers"/>
</flow>
<flow name="VIRL-Restful-Proxy">
<http:listener config-ref="VIRL-UWM-Management-APIs" path="*" doc:name="HTTP"/>
<choice doc:name="GET-vs-POST">
<when expression="#[message.inboundProperties.'http.method' == 'POST']">
<object-to-string-transformer doc:name="Object to String"/>
<logger message="Set the payload of type string - since it's a post request." level="INFO" doc:name="Logger"/>
</when>
<otherwise>
<logger message="Not setting payload transformation as it's a GET request." level="INFO" doc:name="Logger"/>
</otherwise>
</choice>
<set-property propertyName="http.disable.status.code.exception.check" value="false" doc:name="Disable Exception Check"/>
<logger message=" payload is: #[message.payload], method is: #[message.inboundProperties.'http.method'], Request URI is: #[message.inboundProperties.'http.request.uri'], message is: #[message]" level="INFO" doc:name="Logger"/>
<flow-ref name="copy-headers" doc:name="Copy HTTP Headers"/>
<http:request config-ref="Actual-Virl-Enpoint-for-UWM" path="#[message.inboundProperties.'http.request.uri']"
method="#[message.inboundProperties.'http.method']" responseTimeout="60000" doc:name="VIRL End Point"/>
<logger message="response payload: #[message]" level="INFO" doc:name="Logger"/>
<flow-ref name="copy-headers" doc:name="Copy HTTP Headers"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger level="DEBUG" message="#[exception.exceptions]" doc:name="Logger"/>
</catch-exception-strategy>
</flow>
<sub-flow name="copy-headers" >
<copy-properties propertyName="*" doc:name="Copy All HTTP Headers"/>
<remove-property propertyName="Content-Length" doc:name="Remove Content Length"/>
<remove-property propertyName="MULE_*" doc:name="Remove MULE Properties"/>
<remove-property propertyName="X_MULE*" doc:name="Remove X_MULE Properties"/>
<remove-property propertyName="X-MULE*" doc:name="Remove X-MULE Properties"/>
</sub-flow>
</mule>
thanks
This is a bug in Mule's code: I've reported it as such, you can track MULE-8342.
In the meantime, you can try the following:
If you have control of the remote server, add a Content-Disposition header in its multipart responses.
Temporarily use an http:outbound-endpoint in lieu of http:request, until the above bug is fixed.

How to get the incoming cookies to a Mule HTTP end point

I'm using Mule EE 3.5.2.
I'm posting an HTTP request (PostMan) with a cookie header, to an incoming HTTP end point in Mule. How can I read this Cookie?
In practice this cookie will be coming through an NGinX proxy; i need it to pass to another application.
First make sure your connector have enableCookies="true".
Then you'll find a inboundProperty called cookies of type Lorg.apache.commons.httpclient.Cookie.
To access them just #[message.inboundProperties['cookies'].
Here's how to save the cookies from a rest response in a session variable without a custom java class.
<set-session-variable variableName="incomingCookies" value="#[org.mule.transport.http.CookieHelper.parseCookiesAsAClient(message.inboundProperties['set-cookie'],null)]" doc:name="Set incomingCookies as Session Variable"/>
<set-variable variableName="cookie-name" value="#[org.mule.transport.http.CookieHelper.getCookieValueFromCookies(incomingCookieMap,'cookie-name')]" doc:name=“Set cookie-name as Flow Variable”/>
You can use a similar approach for extracting cookies from a rest request using the parseCookiesAsAServer method from the CookieHelper class.
More info on the CookieHelper class is here https://www.mulesoft.org/docs/site/3.8.0/apidocs/org/mule/transport/http/CookieHelper.html
That doesn't work anymore with the new http:listener component.
Setting that property will give :
org.xml.sax.SAXParseException: cvc-complex-type.3.2.2: Attribute 'enableCookies' is not allowed to appear in element 'http:listener'.
So how to do this with the new http:listener component...
A problem I had was that I needed to access the cookies that came in and Mule only provides the cookies in an unformatted string.
So this is an option a friend of mine developed, which I enhanced a bit to get easy access to the cookies in a flow:
package transformers;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.api.transport.PropertyScope;
import org.mule.transformer.AbstractMessageTransformer;
import org.mule.transport.http.CookieHelper;
import org.apache.commons.httpclient.Cookie;
public class CookieGrabber extends AbstractMessageTransformer {
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
Object _CookieHeader = message.getInboundProperty("Cookie");
List<Cookie> _CookieList = null;
Map<String,String> _CookieMap = new HashMap<String,String>();
try {
//Grab the cookies from the header and put them into a List
_CookieList = (List<Cookie>) Arrays.asList(CookieHelper.parseCookiesAsAServer(_CookieHeader.toString(),
new URI("" + message.getInboundProperty("host"))));
//And put them in a convenient List which can be accessed from the flow
message.setProperty("incomingCookieList", _CookieList, PropertyScope.SESSION);
//Let's also put them in a nice Map, since incoming cookies will
//usually only contain a name and a value, so let's get easy access to them by their name.
for (Cookie _Cookie : _CookieList){
_CookieMap.put(_Cookie.getName(), _Cookie.getValue());
}
message.setProperty("incomingCookieMap", _CookieMap, PropertyScope.SESSION);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return message;
}
}
Then there is this flow example which shows how to use this code snippet.
It contains a listener that sets some cookies, forwards it to a "proxy", which will read the cookies, but also forward the request to another endpoint, making it a transparent proxy, but which does read the cookies in the process.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json"
xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
version="EE-3.6.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
<custom-transformer class="transformers.CookieGrabber"
name="MyCookieTranformer"
doc:name="Java"/>
<http:listener-config name="HTTP_Configuration_CookieHandlerExample"
host="0.0.0.0"
port="8080"
doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration"
host="localhost"
port="8080"
doc:name="HTTP Request Configuration"/>
<flow name="CookieSetterFlow">
<http:listener config-ref="HTTP_Configuration_CookieHandlerExample"
path="/setCookies/*"
doc:name="setCookies"
doc:description="Call this module by entering http://localhost:8080/setCookie"/>
<message-properties-transformer doc:name="Set the cookies"
doc:description="Set some random cookies in the header">
<add-message-property key="Cookie"
value="token=abcde; name=dennis"/>
</message-properties-transformer>
<http:request config-ref="HTTP_Request_Configuration"
path="/proxyCookie"
method="GET"
doc:name="call proxyCookies"
doc:description="Invoke the cookieReceiver with the cookies we've just set. Note the failure status code validator with a non-existing http code. It's a nasty bug, but it works like this...">
<http:failure-status-code-validator values="00000"/>
</http:request>
</flow>
<flow name="CookieProxyFlow">
<http:listener config-ref="HTTP_Configuration_CookieHandlerExample"
path="/proxyCookie"
doc:name="proxyCookies"
doc:description="This connector will proxy the cookieReceiver"/>
<transformer ref="MyCookieTranformer"
doc:name="GrabCookies"
doc:description="Use our custom transformers.CookieGrabber class to put the cookies in a nice java.util.List in a session variable."/>
<logger message="CookieProxy: Value of cookie "token": "#[sessionVars.incomingCookieMap.get('token')]"."
level="INFO"
doc:name="Have a cookie!"
doc:description="Let get a cookie value, simply by referring the name of it as the key from our map"/>
<flow-ref name="copy-and-clean-headers"
doc:name="copy-and-clean-headers"
doc:description="Cope the headers and clean the Mule stuff from the headers to forward it clean to the receiver."/>
<set-property propertyName="host"
value="localhost"
doc:name="Set Host"
doc:description="Now not really necessary, but you'll probably want to set the hostname to the actual service endpoint."/>
<http:request config-ref="HTTP_Request_Configuration"
path="/receiveCookie"
method="GET"
doc:name="forward to receiveCookies"
doc:description="Invoke the cookieReceiver.">
<http:failure-status-code-validator values="00000"/>
</http:request>
<flow-ref name="copy-and-clean-headers"
doc:name="copy-and-clean-headers"
doc:description="Again copy the headers and clean the Mule http stuff."/>
</flow>
<sub-flow name="copy-and-clean-headers" >
<copy-properties propertyName="*"
doc:name="Copy All HTTP Headers"/>
<remove-property propertyName="Content-Length"
doc:name="Remove Content Length"/>
<remove-property propertyName="MULE_*"
doc:name="Remove MULE Properties"/>
<remove-property propertyName="X_MULE*"
doc:name="Remove X_MULE Properties"/>
<remove-property propertyName="http.*"
doc:name="Remove http Properties"/>
</sub-flow>
<flow name="CookieReceiverFlow">
<http:listener config-ref="HTTP_Configuration_CookieHandlerExample"
path="/receiveCookie"
doc:name="receiveCookies"
doc:description="This connector receives the cookies we've just set"/>
<transformer ref="MyCookieTranformer"
doc:name="GrabCookies"
doc:description="Use our custom transformers.CookieGrabber class to put the cookies in a nice java.util.List in a session variable."/>
<logger message="CookieReceiver: Value of cookie "token": "#[sessionVars.incomingCookieMap.get('token')]". Yep, still there :)"
level="INFO"
doc:name="Have a cookie!"
doc:description="Let get a cookie value, simply by referring the name of it as the key from our map"/>
<set-payload value="#[sessionVars.incomingCookieList.toArray(String)]"
doc:name="Put CookieList to payload"
doc:description="Put the session vairable List that contains the cookies in the payload"/>
<json:object-to-json-transformer returnClass="java.lang.String"
doc:name="Object to JSON"
doc:description="Convert our payload to a JSON object"/>
</flow>
</mule>
You can test it by running it and opening this page: http://localhost:8080/setCookies
Hope this helps.
You can fetch the cookies with:
#[headers:INBOUND:cookie] or #[message.inboundProperties['cookie']]

Mule HTTP POST `form-data` conversion to Map

My mule application is receiving a HTTP POST request with the Content-Type as multipart/form-data. I tried to use a custom transformer but do not know how to access the paramters as the object is of class ContentLengthInputStream.
How do I access the form parameters?
I want to convert the parameters into a map. How do I do this?
you can use #[message.inboundAttachments[payload] in a flow, for example, to send a http outbound endpoint:
<message-properties-transformer doc:name="Message">
<add-message-property key="Content-type" value="multipart/form-data/>
</message-properties-transformer>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" doc:name="HTTP" address="http://localhost:9090" mimeType="multipart/form-data"/>
To receive can be used:
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8090" connector-ref="HTTP_HTTPS" doc:name="HTTP" contentType="multipart/form-data"/>
<logger message="#[message.inboundAttachments[payload]]" level="ERROR" doc:name="Logger"/>
You can use a transformer(AbstractMessageTransformer) and get the payload with:
DataHandler inboundAttachment = message.getInboundAttachment("AttachmentName");

How to set content type = "application/json" in mule.?

I have a HTML file which consists of a Form and it takes certain parameters from the User and when the URL is hit, a Mule service (written in Java) is called and it returns a JSON string. Now how can I set Content-type = application/json in either Mule or Java, so that browser know that it is getting a JSON?
My Mule config file is :
<custom-transformer name="HttpParams" class="org.mule.transport.http.transformers.HttpRequestBodyToParamMap" />
<message-properties-transformer name="HttpResponse">
<add-message-property key="Content-Type" value="application/json" />
<add-message-property key="http.status" value="303" />
</message-properties-transformer>
<flow name="jcars">
<http:inbound-endpoint address="http://localhost:11221/jcars" transformer-refs="HttpParams" responseTransformer-refs="HttpResponse">
<not-filter>
<wildcard-filter pattern="/favicon.ico"/>
</not-filter>
</http:inbound-endpoint>
<component class="defaults.basicapp.jcars"/>
</flow>
And my Java class is (Jcars) :
public String onEvent(Object obj){
String json = "{{"id":0,"model":"suzuki","make":"2002","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2003","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2004","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2005","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2006","ps":true,"price":101.2,"bhp":12.6}}";
return json;
}
The browser is displaying the string as it is. It does not know that the content type is application/json. What should I do?
Add a response message properties transformer in your flow in order to set the content type:
<response>
<message-properties-transformer>
<add-message-property key="Content-Type" value="application/json" />
</message-properties-transformer>
</response>

Resources