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

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

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.

Https soap service in mule

I have a requirement where soap based service needs to be consumed and in order to achieve that I had used WSConsumer component in Mule.
Where we give the service URL in the properties file and refer to it.
<ws:consumer-config name="Web_Service_Consumer" wsdlLocation="serviceApi.wsdl"
service="serviceAPI" port="serviceApiSoap12Port" serviceAddress="${serviceurl}"
doc:name="Web Service Consumer"/>
Now after the development we came to know that QA web service is a HTTPS web service and while hitting the service following exception is received
SSLHandshakeException: General SSLEngine problem
I'm able to hit the service with Http:request connector as following
<http:request-config name="HTTP_Request_Configuration" host="${host}" port="${port}"
doc:name="HTTP Request Configuration" protocol="HTTPS">
<tls:context>
<tls:trust-store insecure="true" />
</tls:context>
</http:request-config>
But the issue with above config is it won't work for HTTP configuration.
I should be able to connect to both HTTP & HTTPS as I have different environments.
Is there a way where I can achieve this with ws:consumer??
I assume the HTTP connector configuration shown is the one queried by your WS Consumer connector. A simple solution would be to configure the protocol of your HTTP config via property file but Mule doesn't play well with it because you may end-up with a TLS Context configured with HTTP and your connector won't work. There is a little trick you can do however: create 2 HTTP configurations - one for HTTP and one for HTTPS:
<http:listener-config name="HTTPS_Config"
protocol="HTTPS"
host="${host}"
port="${port}"
doc:name="HTTPS Config" >
<tls:context>
<tls:key-store type="${keystore.type}"
path="${keystore.path}"
keyPassword="${keystore.keyPassword}"
password="${keystore.password}"/>
</tls:context>
</http:listener-config>
<http:listener-config name="HTTP_Config"
host="${host}"
port="${port}"
doc:name="HTTP Config" >
</http:listener-config>
In a property file, define which configuration (i.e. which protocol) should be used:
host=localhost
port=443
protocol=HTTPS # or HTTP
And finally in your flow, use your property to reference the proper HTTP(S) config:
<flow name="http-testFlow">
<http:listener config-ref="${protocol}_Config" path="/test" doc:name="HTTP"/>
...
</flow>
The trick is to name your configuration ${protocol}_Config such as HTTP_Config and HTTPS_Config so the proper one is used at runtime via config-ref="${protocol}_Config". Mule will then dynamically use the proper configuration when your app is launched. This is entirely transparent for the user as only the protocol (HTTP vs. HTTPS) needs to be configured, and it can be used in any environment.
You can use this differently, the idea is to have Mule pick your HTTP or HTTPS dynamically at runtime.
EDIT: to configure your WS Consumer with HTTPS you'll need to reference a proper HTTP Requester Configuration such as:
<ws:consumer-config name="Web_Service_Consumer"
...
connectorConfig="HTTP_Request_Configuration"/>
<http:request-config name="HTTP_Request_Configuration"
...
<tls:context>
...
</tls:context>
...
/>
See Web Service Consumer documentation for details.
Note: though this solution works I would recommend using HTTPS all the time, for security reasons and to have less differences between your dev/QA/Prod/... environments - among other things.
I faced similar issues, we finally chose to have only an HTTPS config and define via property which keystore to use at runtime. In dev we would use a self-signed certificate and a proper keystore in environments requiring proper security.
Hope this helps.

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"/>

Unexpected 404 using Mule 3.6 HTTP Connector

I'm getting unexpected 404 errors using the new HTTP connector and can't figure out why.
This curl makes the same call I'm trying to make, and works as expected:
curl -H "X-AuntBertha-Signature: AUTH_SIG" \
https://searchbertha-hrd.appspot.com/_ah/api/search/v1/programs/4818166?api_key=MY_API_KEY \
> resources_dump.json
However, this flow does NOT working. Vendor told me that they don't even see the request show up in their logs, so something is funky.
<http:request-config name="AuntBertha_Production" host="searchbertha-hrd.appspot.com" basePath="/_ah/api/search/v1/" doc:name="HTTP Request Configuration" port="443" protocol="HTTPS" />
<!-- clipped... -->
<flow name="FetchResource">
<!-- clipped... -->
<http:request config-ref="AuntBertha_Production" path="/programs/4818166" method="GET" doc:name="Fetch from AB">
<http:request-builder>
<http:query-param paramName="api_key" value="MY_API_KEY"/>
<http:header headerName="X-AuntBertha-Signature" value="AUTH_SIG"/>
</http:request-builder>
<http:success-status-code-validator values="200,404,500"/>
</http:request>
And here are the logs I'm getting in my console (after help from this question):
DEBUG 2015-07-14 16:19:55,202 [[resource_bulk_upload].HTTP_Default_Listener.worker.01] com.ning.http.client.providers.grizzly.GrizzlyConnectionsPool: [poll] Found pooled connection [TCPNIOConnection{localSocketAddress={/192.168.0.2:49878}, peerSocketAddress={searchbertha-hrd.appspot.com/209.85.147.141:443}}] for uri [https://searchbertha-hrd.appspot.com:443].
DEBUG 2015-07-14 16:19:55,203 [[resource_bulk_upload].HTTP_Default_Listener.worker.01] com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider: REQUEST: HttpRequestPacket (
method=GET
url=/_ah/api/search/v1/programs/4818166
query=api_key=MY_API_KEY
protocol=HTTP/1.1
content-length=-1
headers=[
Host=searchbertha-hrd.appspot.com:443
X-AuntBertha-Signature=AUTH_SIG
Connection=keep-alive
Accept=*/*
User-Agent=NING/1.0]
)
DEBUG 2015-07-14 16:19:55,262 [[resource_bulk_upload].http.requester.AuntBertha_Production(3) SelectorRunner] com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider: RESPONSE: HttpResponsePacket (
status=404
reason=Not Found
protocol=HTTP/1.1
content-length=-1
committed=false
headers=[
cache-control=no-cache, no-store, max-age=0, must-revalidate
pragma=no-cache
expires=Fri, 01 Jan 1990 00:00:00 GMT
date=Tue, 14 Jul 2015 21:19:49 GMT
vary=X-Origin
content-type=text/html; charset=UTF-8
x-content-type-options=nosniff
x-frame-options=SAMEORIGIN
x-xss-protection=1; mode=block
server=GSE
alternate-protocol=443:quic,p=1
accept-ranges=none
transfer-encoding=chunked]
)
If I change the request to ping e.g. google.com instead, it works as expected. What am I missing here? What's the mismatch between my working curl and broken <flow>?
404 not found means it did connect somewhere and got a 404 response back.
So your call is actually successful from a network perspective.
So the code basically works. It could be either like David suggested a Header issue, like user-agent is wrong or the IP/domain calling is wrong, or the Mule node executing the request has some custom proxy configuration or similar. But your statement of "code does not work", I am not sure, the code actually works, it seems the configuration is what does not work.

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

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.