HTTP post request is getting intermittently called via C# client in mule 3.6 - mule

I am hosting webservice using mule 3.6.
I observed POST HTTP request is working fine with java client. But C# client this webservice is getting called intermittently i.e first call is ok, second time out , third call is ok , fourth time out and so on.
GET HTTP request is working fine with C# client
Below is the sample of mule-flow.xml
<http:listener-config name="Port1_WS_Listener" host="0.0.0.0" port="7001" doc:name="WS Listener">
<http:worker-threading-profile maxThreadsActive="20" maxThreadsIdle="10" threadTTL="10000" threadWaitTimeout="5000"/>
</http:listener-config>
<http:listener-config name="Port2_WS_Listener" host="0.0.0.0" port="7002" doc:name="WS Listener">
<http:worker-threading-profile maxThreadsActive="20" maxThreadsIdle="10" threadTTL="10000" threadWaitTimeout="5000"/>
</http:listener-config>
<flow name="WSFlow">
<composite-source>
<http:listener config-ref="Port1_WS_Listener" path="getAttributes1"
doc:name="Port1 " allowedMethods="POST"/>
<http:listener config-ref="Port2_WS_Listener" path="getAttributes2"
doc:name="Port2" allowedMethods="POST"/>
</composite-source>
<component doc:name="java : WSHandler">
<interceptor-stack ref="default" />
<spring-object bean="httpWSHandler" />
</component>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger level="ERROR" message="#[exception]" doc:name="Logger" />
</catch-exception-strategy>
</flow>
C# client sample code
poststring value would be like param=[{'empId':'123', 'empName':'xyz'}]
WebRequest webRequest = (HttpWebRequest)WebRequest.Create(requestUrl);
webRequest.Method = "POST";
webRequest.Timeout = Timeout;
byte[] postBytes = Encoding.UTF8.GetBytes(postString);
webRequest.ContentType = "application/x-www-form-urlencoded";
StreamWriter writer = new StreamWriter(webRequest.GetRequestStream());
writer.WriteLine(postString);
writer.Close();
WebResponse wsResponse = webRequest.GetResponse();
Console.WriteLine("Response Successful");
Stream dataStream = wsResponse.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string response = reader.ReadToEnd();
dataStream.Close();
Console.WriteLine("Response Closed");
Curl output
Note: in below out parameter value has been replaced with dummy parameter hence content length value may differ
About to connect() to localhost port 7002
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 7002
> POST /getAttributes2 HTTP/1.1
> User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8
> Host: localhost:7002
> Accept: */*
> Content-Length: 417
> Content-Type: application/x-www-form-urlencoded
>
> param=[{'empId':'123', 'empName':'xyz'}]HTTP/1.1 200
< MULE_ENCODING: US-ASCII
< Content-Length: 719
< Date: Fri, 31 Jul 2015 09:19:20 GMT
Connection #0 to host localhost left intact
* Closing connection #0
[{"company":"xyz","department":"xyz"}]

I have figured out solution , seems we need to use http-proxy like below
HTTP Proxy
<pattern:http-proxy name="http-proxy-sample">
<http:inbound-endpoint address="http://0.0.0.0:10011/getEmployeeAttributesProxy" />
<http:outbound-endpoint address="http://0.0.0.0:10001/getEmployeeAttributes" />
</pattern:http-proxy>

I experienced the same problem with C# HTTP POST requests going through the APIKit to the new HTTP Listener to the same flow in rapid succession. I worked around it by switching back to the deprecated HTTP Inbound Endpoint, where it is not a problem.
<http:inbound-endpoint doc:name="HTTP" exchange-pattern="request-response" path="api/v1/" host="${http.cs-testing-tools.host}" port="${http.cs-testing-tools.port}" />
When monitoring the flows using Mule Management Console, the calls which timeout are never registered by Mule, so it appears that the HTTP listener never gets a payload to process.
Nov 18 2015 UPDATE - After some discussion with Mule support, this is caused by the interaction between C# and the library used by the new HTTP Listener. The behavior manifests as every other POST timing out.
You can work around this on the C# side as follows:
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ServicePoint.Expect100Continue = false;

You can add Settings to app.config or web.config in your C# project
<system.net>
<settings>
<servicePointManager expect100Continue="false"/>
</settings>
</system.net>

Related

Error Propagate/Transform message component doesn't overwrite default behaviour of Mule4

I have create my flows using APIKIT Router. The raml main flow+post://XX flow. Main flow and my POSt flow have Error handler components
MAIN FLOW:
<flow name="raml-main">
<http:listener .....">
<http:response statusCode="#[vars.httpStatus default 200]">
<http:body ><![CDATA[ ]]></http:body>
<http:headers><![CDATA[#[vars.outboundHeaders default {}]]]></http:headers>
</http:response>
<http:error-response statusCode="#[vars.httpStatus default 500]">
<http:body ><![CDATA[#[output application/json --- error.description]]]>
</http:body>
<http:headers><![CDATA[#[vars.outboundHeaders default {}]]]>
</http:headers>
</http:error-response>
</http:listener>
<apikit:router config-ref="raml-config" />
<error-handler>
<on-error-propagate type="APIKIT:BAD_REQUEST">
<logger level="INFO" doc:name="Logger" doc:id="aa51777e-c1c6-42d2-ba68-b51c45c9aeac" message="Im in MAIN FLOWWWW"/>
<ee:transform xsi:schemaLocation="http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd" doc:id="4f00abf2-0b58-419e-8d9a-d3ef60e356ac">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{message: "BadMAIN request"}]]></ee:set-payload>
</ee:message>
<ee:variables>
<ee:set-variable variableName="httpStatus"><![CDATA[400]]></ee:set-variable>
</ee:variables>
</ee:transform>
</on-error-propagate>
POST FLOW
<flow name="post:\notifications:raml-config">
<json:validate-schema doc:name="Validate schema" doc:id="e447c719-60e2-4f34-aeb9-0b446a1a5eda" schema="schemas/event.json"/>
<choice>
.............................
</choice>
<error-handler >
<on-error-propagate type="JSON:SCHEMA_NOT_HONOURED" enableNotifications="true" logException="true">
<logger level="INFO" doc:name="Logger" doc:id="c818b292-5d89-48eb-aa8d-b7918daa8f0c" message="It is under post flow"/>
<ee:transform xsi:schemaLocation="http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd" doc:id="e8fb927d-edb8-405a-b853-600b4788b719">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{message: "Bad Request"}]]></ee:set-payload>
</ee:message>
<ee:variables>
<ee:set-variable variableName="httpStatus"><![CDATA[400]]></ee:set-variable>
</ee:variables>
</ee:transform>
</on-error-propagate>
</error-handler>
</flow>
If I update payload under Transform processor at POST flow or RAML Main flow, it never gets reflected in the output. Say currently I get 400 bad request.
In the Transform component, if i change message, im not getting my modified message.
Why is that?
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{message: "Bad Request USER ERRROR.."}]]></ee:set-payload>
</ee:message>
RAML CONFIG
/notifications:
post:
headers:
Authorization:
required: false
type: string
responses:
'200':
description: OK
'400':
description: BAD REQUEST
'401':
description: NOT AUTHORIZED
400 means there is no such end point. It means your flow never gets invoked. There is another end point for which Mule is listening.
Luckily Mule reports that url is wrong amd what kind of urls it is listening. Like this
INFO 2020-05-07 07:32:22,539 [http.listener.06 SelectorRunner] org.mule.service.http.impl.service.util.DefaultRequestMatcherRegistry: No listener found for request: (GET)/badurl
INFO 2020-05-07 07:32:22,539 [http.listener.06 SelectorRunner] org.mule.service.http.impl.service.util.DefaultRequestMatcherRegistry: Available listeners are: [([*])/console/*, ([*])/, ([*])/api/*]
Of course if you hit another server or another port or protocol then nothing knows about this request. But, since you have the answer - 400 - then you probably hit your server.
https://simpleflatservice.com/mule4/Recognize400Error.html
Default error handler and response could be also set in the http listener in the Responses - Error Response section
The HTTP response 400 bad request means that the HTTP request is not matching an expected format. It is possible that APIKit is validating the request against the RAML. In that case APIKit will raise the error and it will not execute the post:\notifications:raml-config flow. Have you confirmed the flow is executed, for example with a logger?

Can't send "Authorization" header to endpoint - HTTP Module - Mulesoft 3.9

I'm trying to call an API Rest from a flow in mule. This API has a basic auth protocol, so I need to send the header "Authorization: Basic XXXXXXX".
The issue that I encounterd is that on the Anypoint Studio, when I'm cofiguring the HTTP Request, I don't get the option of Basic Auth on the Authentication tab, I only see NTLM.
I already tried to set the header manualy, But it gets ignored.
Already tried to include this:
< http:basic-authentication username="${ofsc.clientId}#${ofsc.instance}" password="${ofsc.clientKey}"/>
on the http:request-config, and it didn't work either.
This is the Mule config:
< http:listener-config name="Gateway" host="localhost" port="8281" basePath="/base" doc:name="HTTP Listener Configuration"/>
< http:request-config name="OFSC" host="api.etadirect.com" basePath="/rest/ofscCore/v1" doc:name="HTTP Request Configuration" port="443" protocol="HTTPS">
< http:basic-authentication username="${ofsc.clientId}#${ofsc.instance}" password="${ofsc.clientKey}"/>
< /http:request-config>
< spring:beans>
< spring:bean id="Bean" name="BasicAuthEncode" class="tools.BasicAuthEncode" />
< /spring:beans>
< context:property-placeholder location="env.properties"/>
<flow name="TestFlow">
<http:listener config-ref="Gateway" path="/test" doc:name="HTTP">
<http:response-builder disablePropertiesAsHeaders="true"/>
<http:error-response-builder disablePropertiesAsHeaders="true"/>
</http:listener>
<invoke object-ref="BasicAuthEncode" method="encodeCredentials" doc:name="LPM" methodArgumentTypes="java.lang.String" methodArguments="${ofsc.clientId}#${ofsc.instance}:${ofsc.clientKey}" name="LPM2"/>
<set-variable variableName="credentials" value="Basic #[message.payloadAs(java.lang.String)]" doc:name="Creds"/>
<http:request config-ref="OFSC" path="/activities/3818" method="GET" doc:name="HTTP">
<http:request-builder>
<http:header headerName="Content-Type" value="application/json"/>
</http:request-builder>
<http:success-status-code-validator values="200,400,401,404,403"/>
</http:request>
<logger message="#[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
</flow>
I'm probably doing something relly wrong, but couldn't find the answer. Hope you guys can help me
Thanks
uncheck the "enable cookie" in the http configuration resolved the issue.
The issue was on my properties file.
The values where wrapped in quotes, and the base64 encoding was giving me a wrong string.

Error sending HTTP request. Message payload is of type: LinkedHashMap [MULE ESB]

I'm new in MULE ESB, I have this code and i'm trying sending a http request using http:request with the following format:
"http: //www.host.com/api/commentThreads?key=val&part=val2&..."
<file:inbound-endpoint connector-ref="fileConnector" path="C:/tmp/input"
doc:name="Reader File Configuration" responseTimeout="10000"
encoding="UTF-8" mimeType="text/plain"
pollingFrequency="20000">
<file:filename-wildcard-filter pattern="*.json"/>
</file:inbound-endpoint>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<logger level="INFO" message="#[payload]" doc:name="Logger" />
<http:request config-ref="HTTP_Request_Configuration" path="/commentThreads" method="GET" port="443" doc:name="HTTP Request">
<http:request-builder>
<http:query-param paramName="key" value="#[message.payload.key]"/>
<http:query-param paramName="allThreadsRelatedToChannelId" value="#[message.payload.allThreadsRelatedToChannelId]"/>
<http:query-param paramName="part" value="#[message.payload.part]"/>
</http:request-builder>
</http:request>
But I'm having this error:
Message : Error sendinbut g HTTP request. Message payload is of type: LinkedHashMap
Code : MULE_ERROR--2
Exception stack is:
null (java.util.concurrent.TimeoutException) org.glassfish.grizzly.impl.SafeFutureImpl$Sync:357 (null)
Error sending HTTP request. Message payload is of type: LinkedHashMap (org.mule.api.MessagingException)
org.mule.module.http.internal.request.DefaultHttpRequester:190
(http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
The question is how can I do to make a http request with that format using the map?
According to documents
https://www.mulesoft.org/documentation/display/current/HTTP+Request+Connector#HTTPRequestConnector-HTTPRequestBody
The Mule Message payload is converted into a byte array and sent as
the HTTP Request's body. This behavior is carried out always, except
in the following scenarios:
The Mule Message's Payload is a Map of keys and values
Generate the Request Body with
Content-Type:application/x-form-urlencoded
Whenever the message payload is a Map, the connector automatically
generates an HTTP request with the header
Content-Type:application/x-www-form-urlencoded. The keys and values of
the map in the payload are converted into form parameter keys and
values in the body of the HTTP request.
I suppose the map is converter automatically for the request. Correct me if I'm wrong
It was necessary to make a transformation before the
<json: json-to-object-transformer returnClass = "java.util.Map" doc: name = "JSON to Object" />
It is corrected by putting
<byte-array-to-string-transformer doc: name = "Byte Array to String" />
The error you're getting actually is not because your request has something wrong (or at least is not failing at that stage) but that your app is not being able to connect to the http server you're trying to send the request to. You can infer this by the exception you're getting java.util.concurrent.TimeoutException.
In order to troubleshoot please verify the host name and port are typed correctly.

Mule test code for inbound file polling

I'm new to Mule ESB.
I have the following config file for Mule which was taken from the Spell Checker tutorial:
<file:connector name="FILE" streaming="false" doc:name="File" autoDelete="true" validateConnections="false"/>
<flow name="SpellCheckerFlow1" doc:name="SpellCheckerFlow1">
<file:inbound-endpoint connector-ref="FILE" path=".\xmlIn" pollingFrequency="3000" responseTimeout="10000" doc:name="Incoming File" moveToDirectory=".\xmlProcessed"/>
<http:outbound-endpoint exchange-pattern="request-response" host="www.google.com/tbproxy/spell?lang=en" port="80" doc:name="Invoke API"/>
<echo-component doc:name="Echo"/>
<file:outbound-endpoint path=".\xmlOut" outputPattern="#[function:datestamp:dd-MM-yy]_#[function:systime].xml" responseTimeout="10000" doc:name="File"/>
</flow>
I'm trying to extend the FunctionalTestCase class and test this flow. Below is the extracted code I'm using to do that:
MuleClient client = new MuleClient(muleContext);
client.dispatch("file://./xmlIn", "<valid_xml />", null);
MuleMessage message = client.request("file://./xmlOut", 1000000000);
When I execute this code it creates a data file in the /xmlIn folder. The rest of the flow does not get executed. The flow should poll on this folder to pick up the file.
Thanks in advance!
The time-out parameter is ineffective when requesting from a file endpoint: Mule is not going to wait for the file to appear.
This means that your test doesn't block and always fails. The easiest/less refined way to solve the issue is to loop on a { Thread.wait(); client.request(); } until you get a non-null message, ie until the file in xmlOut has been read.
No need to add a retry counter: Mule's FunctionalTestCase will automatically fail the test after getTestTimeoutSecs() has elapsed (60 seconds by default).
Side notes:
To make your config work in my environment, I had to replace the .\ with ./ in the file paths of the XML config.
The outbound HTTP endpoint is mis-configured: the path is mixed in the host, use instead:
<http:outbound-endpoint exchange-pattern="request-response"
host="www.google.com" path="tbproxy/spell?lang=en" port="80"
doc:name="Invoke API" />
It's slightly more efficient to get the Mule client this way:
MuleClient muleClient = muleContext.getClient();

XMLStreamReader parser affects MuleEventContext

I'm using Mule Studio (Mule 3.2.1CE) to configure a proxy service which simply calls a remote web service. Everything works fine with calling and getting the proper response (using soapUI). I want to log SOAP message received within the ESB. I'm getting a DepthXMLStreamReader message as expected by the CXF component but I'm facing an odd behavior when I use XMLStreamReader object's next() method. Here is the code I use:
public Object onCall(MuleEventContext context) throws Exception {
MuleMessage message = context.getMessage();
DepthXMLStreamReader streamReader = new DepthXMLStreamReader((XMLStreamReader) message.getPayload());
while(streamReader.hasNext()){
streamReader.next();
if(streamReader.getEventType() == XMLStreamReader.START_ELEMENT)
{
System.out.println(streamReader.getLocalName());
}
}
return context.getMessageAsString();
The above code works and prints XML elements but I get the following error afterwards:
org.apache.cxf.interceptor.Fault: Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=..., connector=HttpConnector
...
Caused by: org.mule.transport.http.HttpResponseException: Internal Server Error, code: 500
I tried using StaxUtils.nextEvent and StaxUtils.toNextElement, but no difference in result. I wonder why parsing XML by next() method affects mule context. If I use System.out.println(context.getMessageAsString()); before the return statement it prints "[Messaage could not be converted to string]" but it works before while statement in the above code.
Here is my mule config:
<flow name="wsFlow1" doc:name="wsFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8090" contentType="text/xml" doc:name="HTTP"/>
<cxf:proxy-service bindingId="..." namespace="http://..." service="..." payload="body" wsdlLocation="..." enableMuleSoapHeaders="false" doc:name="SOAP"/>
<component class="mule.ws.SoapLogging" doc:name="Java"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://..." contentType="text/xml" doc:name="HTTP"/>
</flow>
Thanks
I don't think this is related to MuleEventContext.
The in-flight payload is a XMLStreamReader. You consume this XMLStreamReader in your component then try to return a String representation of it, which is not possible anymore because you've consumed it.
Try the following in your component:
Serialize the XMLStreamReader to a String
Log this String or part thereof
Return this String from the component.