user3165854 user3165854 - 13 days ago 8
AngularJS Question

HTTP POST request message is not received every time in Mulle when using CORS

I have a set of UI screens written in Angularjs which steps through an example customer order
1. gets the customer
2. gets the products
3. creates the order

The UI and Mule are configured for Cross Origin Resource Sharing (CORS) and the HTTP GET calls work correctly but the HTTP POST request shows in the Chrome DevTools Network console as an error and has been cancelled.

When I run Mule in debug mode, the HTTP POST request is not received every time from the UI and most often I have to run the 3 customer order steps twice to see the POST request trigger the create order workflow which appears to complete successfully when triggered. Everytime though the POST call shows as cancelled in Chrome DevTools.

Does anyone know what may be causing this behaviour and how to get the POST message to trigger the Mule workflow everytime?

I am not sure if the OPTIONS message that is sent as part of the CORS procedure is then not triggering the POST because of something in the Mule code and the reason it works second time is because the OPTIONS reply has been cached so it sends the POST request straight away or whether there is something else.

XML Flow:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:cors="http://www.mulesoft.org/schema/mule/cors" xmlns:apikit="http://www.mulesoft.org/schema/mule/apikit" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/cors http://www.mulesoft.org/schema/mule/cors/current/mule-cors.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/apikit http://www.mulesoft.org/schema/mule/apikit/current/mule-apikit.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<apikit:config name="test-order-config" raml="test-order.raml" consoleEnabled="true" consolePath="console" doc:name="Router">
<apikit:flow-mapping resource="/orders/order" action="post" content-type="application/json" flow-ref="post:/orders/order:test-order-config"/>
</apikit:config>

<cors:config name="Cors_Configuration" doc:name="Cors Configuration">
<cors:origins>
<cors:origin url="*">
<cors:methods>
<cors:method>POST</cors:method>
<cors:method>DELETE</cors:method>
<cors:method>PUT</cors:method>
<cors:method>GET</cors:method>
<cors:method>OPTIONS</cors:method>
</cors:methods>
<cors:headers>
<cors:header>Content-Type</cors:header>
</cors:headers>
</cors:origin>
</cors:origins>
</cors:config>

<flow name="test-order-main">
<http:listener config-ref="HTTP_Experience_Listener_Configuration" path="/*" doc:name="HTTP"/>
<cors:validate config-ref="Cors_Configuration" publicResource="true" acceptsCredentials="false" doc:name="CORS Validate"/>
<apikit:router config-ref="test-order-config" doc:name="APIkit Router"/>
<exception-strategy ref="test-order-apiKitGlobalExceptionMapping" doc:name="Reference Exception Strategy"/>
</flow>

<flow name="set-access-control-allow">
<set-property propertyName="Access-Control-Allow-Origin" value="*" doc:name="Set Access Control Allow Origin"/>
<set-property propertyName="Access-Control-Allow-Credentials" value="false" doc:name="Set Access Control Allow Credentials"/>
<set-property propertyName="Access-Control-Allow-Methods" value="GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS" doc:name="Set Access Control Allow Methods"/>
<set-property propertyName="Access-Control-Allow-Headers" value="DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,origin,authorization,accept,client-security-token" doc:name="Set Access Control Allow Headers"/>
</flow>

<flow name="get:/products:test-order-config">
<set-payload value="#['{ &quot;getProducts&quot;: { &quot;productsList&quot;: [{ &quot;productId&quot;: &quot;001&quot;, &quot;name&quot;: &quot;test_product1&quot;}]}}']" doc:name="Set Payload"/>
<flow-ref name="set-access-control-allow" doc:name="set-access-control-allow"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>

<flow name="get:/customer/{customerId}:test-order-config">
<set-payload value="#['{&quot;getCustomer&quot;:{&quot;customerId&quot;:&quot;1234567890&quot;,&quot;title&quot;:&quot;MR&quot;,&quot;Name&quot;:&quot;John&quot;}}']" doc:name="Set Payload"/>
<flow-ref name="set-access-control-allow" doc:name="set-access-control-allow"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>

<flow name="post:/orders/order:test-order-config">
<set-payload value="#['{&quot;createOrder&quot;:{&quot;orderId&quot;:&quot;8a493ecd-e842-4ca2-b33b-a03aa9136673&quot;,&quot;success&quot;:true}}']" doc:name="Set Payload"/>
<flow-ref name="set-access-control-allow" doc:name="set-access-control-allow"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>

<apikit:mapping-exception-strategy name="test-order-apiKitGlobalExceptionMapping">
<apikit:mapping statusCode="404">
<apikit:exception value="org.mule.module.apikit.exception.NotFoundException"/>
<set-property propertyName="Content-Type" value="application/json" doc:name="Property"/>
<set-payload value="{ &quot;message&quot;: &quot;Resource not found&quot; }" doc:name="Set Payload"/>
</apikit:mapping>
<apikit:mapping statusCode="405">
<apikit:exception value="org.mule.module.apikit.exception.MethodNotAllowedException"/>
<set-property propertyName="Content-Type" value="application/json" doc:name="Property"/>
<set-payload value="{ &quot;message&quot;: &quot;Method not allowed&quot; }" doc:name="Set Payload"/>
</apikit:mapping>
<apikit:mapping statusCode="415">
<apikit:exception value="org.mule.module.apikit.exception.UnsupportedMediaTypeException"/>
<set-property propertyName="Content-Type" value="application/json" doc:name="Property"/>
<set-payload value="{ &quot;message&quot;: &quot;Unsupported media type&quot; }" doc:name="Set Payload"/>
</apikit:mapping>
<apikit:mapping statusCode="406">
<apikit:exception value="org.mule.module.apikit.exception.NotAcceptableException"/>
<set-property propertyName="Content-Type" value="application/json" doc:name="Property"/>
<set-payload value="{ &quot;message&quot;: &quot;Not acceptable&quot; }" doc:name="Set Payload"/>
</apikit:mapping>
<apikit:mapping statusCode="400">
<apikit:exception value="org.mule.module.apikit.exception.BadRequestException"/>
<set-property propertyName="Content-Type" value="application/json" doc:name="Property"/>
<set-payload value="{ &quot;message&quot;: &quot;Bad request&quot; }" doc:name="Set Payload"/>
</apikit:mapping>
</apikit:mapping-exception-strategy>

</mule>


Chrome DevTools shows the Request Headers as provisional in the POST call it shows as cancelled even though sometimes the request is received by Mule and processed correctly.

enter image description here

enter image description here

enter image description here

enter image description here

HTTP POST call in angularjs code:

postContent: function (link, data) {
$http({
method: 'POST',
url: link,
headers: {'Content-Type':'application/json'},
data: angular.toJson(data)
}).success(function (responseData) {
//do stuff with response
var returnData = responseData;
}).error(function (e) {
//do stuff with response
var error = e;
});
}

Answer

Just add OPTIONS in the authorized requests :

<cors:methods>
    <cors:method>OPTIONS</cors:method>
</cors:methods>

EDIT the OP also had to delete the Content-type header from his $http call, this is what all the comments are about.

Comments