Why mule's http:rest-service-component does not support PUT method? - mule

I want to call rest service in flow, at first, I use http:outbound-endpoint as following:
<http:outbound-endpoint exchange-pattern="request-response"
address="http://localhost:7081#[message.inboundProperties['http.request']]" doc:name="Call Lower REST" method="PUT">
EDIT:
Request:
PUT http://localhost:8080/ae2/app/add?nonce=23ddd&name=app1&timestamp=123332&user=foo HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/xml
Content-Length: 0
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
It throws an exception:
Root Exception stack trace:
java.lang.Exception: The HTTP method or content type is unsupported!
at org.mule.transport.http.transformers.HttpRequestBodyToParamMap.transformMessage(HttpRequestBodyToParamMap.java:56)
at org.mule.transformer.AbstractMessageTransformer.transform(AbstractMessageTransformer.java:145)
at org.mule.transformer.AbstractMessageTransformer.transform(AbstractMessageTransformer.java:93)
Then I read some document, and I found the http:rest-service-component, it can call the backend rest service, but it does not support PUT method, the document says, and I tried.
So, Why this component does not support PUT? Or is there anthoer component can be used?

It is not being thrown from the outbound endpoint. Somewhere in your flow you are using:
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map" />
In you config here: mule's http-proxy cannot be used in flow? - you are using it a few lines down after your first logger.
This transformer will return the message properties as a hash map of name-value pairs. This transformer handles GET and POST with application/x-www-form-urlencoded content type. This transformer does not support PUT or DELETE.
You are PUTing XML so theres no need to use this transformer.
If you still need it for POST, then you can wrap this transformer in a choice so it only gets used for GET and POST. For example:
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['http.method'] == 'POST']">
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map" />
...
</when>
</choice>
Otherwise remove it.

Related

Enable WS-Addressing in Mulesoft Web service consumer

How to enable WS-Addressing in Web service Consumer of Mulesoft.
When I search for WS-Addressing in mulesoft. It points to CXF. However the docs point that it's recommended to use web service consumer rather than CXF.
So is there any way to enable WS-Addressing. SoapAction is added into the WSDL
POST /esi2/esi-gateway/v2/common/v1 HTTP/1.1
SOAPAction: "http://www.macquarie.com/...."
Host: www.macquarie.com
User-Agent: AHC/1.0
Connection: keep-alive
Accept: */*
Content-Type: text/xml; charset=UTF-8
Content-Length: 1453
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-2004
...................
When Tested in SOAP UI I can find WS-A with all the details filled. How can i get a similar stuff in Mulesoft
Note :- This is the official answer. And it works. Fix the dummy web address in TO, Action and messageID.
Please add the following before webservice consumer . you should be set to go
<set-property propertyName="soap.to" value="<wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.asdfadsf.com/esi/common/v1</wsa:To>" doc:name="Soap.To"/>
<set-property propertyName="soap.Action" value="<wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.xyzdadadf.com/esi/common/1.0/getAuthenticationExpiryRequest</wsa:Action>" doc:name="soap.action"/>
<set-property propertyName="soap.messageID" value="<wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">urn:entity-name:version:1</wsa:MessageID>" doc:name="soap.messageID"/>
I post this in the form for larger community help.

Mulesoft download zip file via APIKit Router

I am having trouble with browser showing save/download prompt for zip file on http endpoint wiht APIKit Router.
I have a sub flow that gets S3 object and sets payload to #[message.payload.getObjectContent] which works fine with http listener going straight to flow, but if using APIKit router browser returns nothing.
I think it might have something to do with my raml.
/GetPackage
get:
responses:
200:
description: Success
body:
200:
application/zip
I also read something about...
Content-Disposition: attachment;filename=file.zip
Some help/direction would be much appreciated
Tnx!
Figured out a solution. It wasn't enough just having application/zip in RAML.
Needed to set two properties in Flow (with Property component):
Content-Disposition: attachment;filename=filename.zip
Content-Type: application/zip
Configuration XML that I used:
<set-property propertyName="Content-Disposition" value="attachment;filename=filename.zip" doc:name="Content-Disposition"/>
<set-property propertyName="Content-Type" value="application/zip" doc:name="Content-Type"/>

Mule HTTPS POST request not working when deployed to Cloudhub

I have a Mule application that is calling an external API over HTTPS using the <http:request connector. When I build and deploy my application locally, the call works fine. When I make a Postman call to the same external API using the exact same payload my Mule app sends, the call works fine. However, when I deploy the Mule app to Cloudhub and make the request - I get a 400 response from the external API.
Here's my flow:
<http:request-config name="mambuRequestConfiguration" protocol="HTTPS" doc:name="HTTP Request Configuration">
<http:basic-authentication username="${mambu.username}" password="${mambu.password}" preemptive="true" />
<tls:context>
<tls:key-store type="jks" path="keystore.jks" alias="${keystore.alias}" keyPassword="${keystore.keypassword}" password="${keystore.password}" />
</tls:context>
</http:request-config>
<flow name="createClientDepositAccount">
<dw:transform-message metadata:id="412fd434-12bb-47a3-9605-9bfc1d9fec46" doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
savingsAccount: {
accountHolderKey: payload.clientKey,
accountHolderType: "CLIENT",
productTypeKey: payload.productKey,
name: payload.clientProductName,
accountType: payload.accountType,
accountState: payload.accountState,
interestRate: payload.interestRate
}
}]]></dw:set-payload>
</dw:transform-message>
<http:request config-ref="mambuRequestConfiguration" path="${mambu.deposit.path}" method="POST" host="${mambu.host}" port="${mambu.port}" doc:name="Mambu: Create Client Deposit Account">
<http:success-status-code-validator values="0..599"/>
</http:request>
<dw:transform-message metadata:id="49f1231f-485f-433c-82c4-3d83856ac442" doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
message: "Account created successfully",
key: payload.savingsAccount.encodedKey
}]]></dw:set-payload>
</dw:transform-message>
</flow>
The external service I'm calling is Mambu, a cloud banking platform. I have a number of other flows in my application all making GET requests to various other Mambu APIs - all work fine (all GET requests are also over HTTPS). The response I'm getting from Mambu is a 400 with the payload:
{"returnCode":3,"returnStatus":"INVALID_API_OPERATION"}
Relevant links to the Mambu documentation are here and here.
I'm unable to replicate the behaviour I'm seeing in Cloudhub on my local instance. The only thing that differs about this call to the others I'm making is that it's a POST request.
In most cases this error is related to the API auto-discovery being improperly configured or corrupt. If API auto-discovery is configured on the Mule application, the best solution is to remove the setting from the Mule application, check if the error is resolved by starting the process again, then reconfigure the auto-discovery.
Bizarrely, the resolution to this was "turn it off and on again" as suggested on a question I posted on the Mulesoft forum. I simply deleted the app from Cloudhub and redeployed it and everything worked as expected. Very strange issue within Cloudhub by the looks of things. Hopefully Mulesoft will resolve...

Mule-ESB HTTP redirect does not work when followRedirects=false

I have a simple flow that didn’t work for mule. In my setup, I am listening on one port for HTTP traffic and forwarding traffic on another port which I believe is the most typical ESB use case. The proxy/gateway flow works except when the target application issues redirect. Does anyone know of any tricks to address this? Note that I can not use the "HTTP-Proxy pattern" from mule as I intend to extend this flow for more complex use case.
Mule Flow
<http:listener-config name=“HTTP_IN" host=“localhost" port="12344" doc:name=“IN_EP" />
<http:request-config name=“HTTP_OUT" host=“localhost" port="8380" doc:name=“OUT_EP"/>
<flow name="test2Flow2">
<http:listener config-ref=“HTTP_IN" path="*" doc:name="IN"/>
<logger level="INFO" doc:name="Request Logger"/>
<http:request config-ref=“HTTP_OUT" path="#[message.inboundProperties.'http.request.path']" method="#[message.inboundProperties.'http.method']" doc:name="OUT" followRedirects="false" />
<response>
<logger level="INFO" doc:name="Response Logger"/>
</response>
</flow>
Case 1: followRedirects=true (default)
In this case mule gets HTTP 302 from target end point and it internally navigates to the redirected page and serves the page to the client. This is great if I am using Mule as a gateway to some web services. However for HTTP traffic from browser, if we allow this to happen, all the relative URLs will break from the rendered page.
Case 2: followRedirects=false
In this case mule gets HTTP 302 from target end point and it drops the response after logging it. Mule just send HTTP 200 on the browser with empty HTML page. See logs below for case 2. I like to send the HTTP 302 response to the end-user.
Request Logged (Case 2)
INFO 2015-10-01 13:01:48,333 [[test2].APP_A_IN.worker.01] org.mule.api.processor.LoggerMessageProcessor:
org.mule.DefaultMuleMessage
{
Message properties:
INVOCATION scoped properties:
INBOUND scoped properties:
accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-encoding=gzip, deflate, sdch
accept-language=en-US,en;q=0.8
cache-control=max-age=0
connection=keep-alive
dnt=1
host=localhost:12344
http.listener.path=/*
http.method=GET
http.query.params=ParameterMap{[]}
http.query.string=
http.relative.path=/app_a
http.remote.address=/127.0.0.1:53372
http.request.path=/app_a
http.request.uri=/app_a
http.scheme=http
http.uri.params=ParameterMap{[]}
http.version=HTTP/1.1
upgrade-insecure-requests=1
user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
x-firephp-version=0.0.6
OUTBOUND scoped properties:
SESSION scoped properties:
}
Response Logged (Case 2)
INFO 2015-10-01 13:01:48,420 [[test2].APP_A_IN.worker.01] org.mule.api.processor.LoggerMessageProcessor:
org.mule.DefaultMuleMessage
{
Message properties:
INVOCATION scoped properties:
INBOUND scoped properties:
date=Thu, 01 Oct 2015 17:01:48 GMT
http.reason=Moved Temporarily
http.status=302
location=http://localhost:8380/app_a/
server=Apache-Coyote/1.1
transfer-encoding=chunked
OUTBOUND scoped properties:
SESSION scoped properties:
}
I think the problem is that you are not copying the properties from the requester to the listener's response. I suggest using a copy-properties element right after the requester. The inbound properties will be lost otherwise: you need them as outbound at that point.
Some properties like the http.status might need to be mapped to headers explicitly using a response-builder though.
HTH

Why Mule http inbound endpoint is always GET request

Why Mule http inbound endpoint is always GET request. I'm logging type of http method
and it always logs type is GET even I specified method type PUT in http inbound end
point.
<http:inbound-endpoint exchange-pattern="request-response"
path="testPath" doc:name="HTTP"
host="localhost" port="8083"
mimeType="application/json"
method="PUT"/>
<logger level="INFO" message="method type #[message.inboundProperties['http.method']]"
doc:name="Logger"/> <--- It always logs method is GET
It never go into following expression block:
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['http.method']=='PUT']">
I would like to set http method as a "PUT" in http inbound endpoint
The method attribute on http:inbound-endpoint is ineffective: you can put any value there, it won't change anything.
As Ale suggested, it's up to the HTTP client to use whatever method you want to receive on Mule's side.