In Apigee, the Assign Message Policy only seems to work on successful responses. If the server responds with an error code, say, 403 Forbidden, the policy does not change the response. Is there any other way to modify error responses in Apigee.
This is my policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="Assign-Message-1">
<DisplayName>Assign Message-1</DisplayName>
<Properties/>
<Remove>
<Headers>
<Header name="Server"/>
</Headers>
</Remove>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
You can modify error responses in Apigee using FaultRules. You can take a look at Apigee's documentation about Fault handling .
The reason your AssignMessage policy is not executed is, that the error happens before your policy is being executed, thus being skipped.
You can either move your AssignMessage policy to be executed earlier in the flow or catch the error using fault handling logic and throw the error when you have executed all the desired logic.
In case of different response message of Success and Error,
I usually create 2 policy of Assign Message, one for Success and other for Error response.
Example of Success:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="AM-ReturnSuccessResponse">
<DisplayName>AM-ReturnSuccessResponse</DisplayName>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="response"/>
<Set>
<Payload contentType="application/json" variablePrefix="#" variableSuffix="#">
#resp.responseMessage#
</Payload>
<StatusCode>{resp.httpStatusCode}</StatusCode>
<ReasonPhrase>{resp.reasonPhrase}</ReasonPhrase>
</Set>
</AssignMessage>
Example of Error:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AssignMessage async="false" continueOnError="false" enabled="true" name="AM-ReturnErrorResponse">
<DisplayName>AM-ReturnErrorResponse"</DisplayName>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="response"/>
<Properties/>
<Set>
<Payload contentType="application/json" variablePrefix="#" variableSuffix="#">
{
"error" : "#resp.error#",
"timeStamp" : "#resp.responseDateTime#"
}
</Payload>
<StatusCode>{resp.httpStatusCode}</StatusCode>
<ReasonPhrase>{resp.reasonPhrase}</ReasonPhrase>
</Set> </AssignMessage>
And then in your flow you have to set condition for routing the policy like this
<Flow name="test">
<Description/>
<Request/>
<Response>
<Step>
<Name>AM-ReturnSuccessResponse</Name>
<Condition>resp.httpStatusCode == 200</Condition>
</Step>
<Step>
<Name>AM-ReturnErrorResponse</Name>
<Condition>resp.httpStatusCode != "200"</Condition>
</Step>
</Response>
</Flow>
Remark: Because normally http status code for success is 200, So I have set the condition like code above. But this is for example, you can design the condition up to your scenario.
Related
Cannot execute BargainFinderMaxRQ query.
I try to execute simple flight search, but
i receive error: DSF server returned an error: Bad EA owner code
My query:
...
<OTA_AirLowFareSearchRQ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.opentravel.org/OTA/2003/05" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Target="Production" Version="5.2.0" ResponseType="OTA" ResponseVersion="5.2.0">
<POS>
<Source PseudoCityCode="PCC">
<RequestorID ID="1" Type="1">
<CompanyName Code="TN"/>
</RequestorID>
</Source>
</POS>
<OriginDestinationInformation RPH="1">
<DepartureDateTime>2019-11-10T11:00:00</DepartureDateTime>
<OriginLocation LocationCode="MOW"/>
<DestinationLocation LocationCode="LED"/>
</OriginDestinationInformation>
<TravelPreferences ValidInterlineTicket="true">
<CabinPref PreferLevel="Preferred" Cabin="Y"/>
</TravelPreferences>
<TravelerInfoSummary>
<SeatsRequested>1</SeatsRequested>
<AirTravelerAvail>
<PassengerTypeQuantity Code="ADT" Quantity="1"/>
</AirTravelerAvail>
</TravelerInfoSummary>
<TPA_Extensions>
<IntelliSellTransaction>
<RequestType Name="50ITINS"/>
</IntelliSellTransaction>
</TPA_Extensions>
</OTA_AirLowFareSearchRQ>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Errors in the response
<Errors>
<Error Type="SCHEDULES" Code="PROCESS" ShortText="DSF server returned an error: Bad EA owner code 'EXT'"/>
<Error Type="IF2" Code="PROCESS" ShortText="No complete journey can be built in IF2/ADVJR1."/>
<Error Type="WORKERTHREAD" Code="TRANSACTIONID" MessageClass="I" ShortText="4259351061194214838"/>
<Error Type="SERVER" Code="ASECT2LAPC00015.IDM.SGDCPROD.SABRE.COM" MessageClass="I" ShortText="27040"/>
<Error Type="DRE" Code="RULEID" MessageClass="I" ShortText="21728"/>
<Error Type="DEFAULT" Code="RULEID" MessageClass="I" ShortText="25238"/>
<Error Type="SCHEDULES" Code="MSG" MessageClass="I" ShortText="NO FLIGHT SCHEDULES FOR QUALIFIERS USED"/>
<Error Type="ERR" Code="ERR" ShortText="Error during Processing"/>
</Errors>
Please refer to the documentation for the Bargain Finder Max API:-
https://developer.sabre.com/sites/default/files/2020-04/BargainFinderMax_NDC_Guide_2020.pdf
The documentation provided has examples for the same.
In all probability, either your PCC is not enabled to consume BFM or the tier level (50, 100, 200) you specified does not match your BFM agreement.
The solution is as under: -
Ensure your PCC is enabled to consume BFM. Contact your Sabre account manager to validate if your PCC has been configured to consume BFM.
Adjust the BFM tier level to the appropriate one according to your BFM agreement.
Review the qualifiers used on your request to ensure those are not overly-restrictive – Example, requesting non-stop flights in a route where non-stop flights do not operate.
In call mediator we can form endpoint using XPath (from the response).But the problem is endpoint is not calling.
<?xml version="1.0" encoding="UTF-8"?>
<api context="/xpath" name="call"
xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" protocol="http">
<inSequence>
<call>
<endpoint key-expression="/root/a"/>
</call>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
following response is from postman.
<root>
<a>http://www.mocky.io/v2/5ca6db71340000132f76b192</a>
</root>
Expected response :
<root>
<name>abcd</name>
<no>82382832</no>
</root>
Firstly, when using the resolving endpoint (using key-expression), we cannot give the URL directly [1]. We have to have the endpoint defined beforehand and should give only the key of the endpoint in the payload.
Secondly, for the key-expression to parse the xpath, the message should be built beforehand. Since call mediator is content-unaware, it will not build the message. Therefore, we should use a content aware mediator to build the message.
Following is the sample inSequence that'd work.
<inSequence>
<log level="full"/>
<call>
<endpoint key-expression="//a"/>
</call>
<respond/>
</inSequence>
Now the payload should be like
<root>
<a>testEndpoint</a>
</root>
Edit:
The endpoint named 'testEndpoint' should be defined with the backend url.
You need to define an endpoint [2]. For example, I'm using an address endpoint.
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="testEndpoint">
<address uri="http://www.mocky.io/v2/5ca6db71340000132f76b192">
<suspendOnFailure>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
<retryDelay>0</retryDelay>
</markForSuspension>
</address>
</endpoint>
Try this. I receieved needed response in Postman, but you should use POST method as your request has a Body.
<api xmlns="http://ws.apache.org/ns/synapse" name="call" context="/xpath">
<resource methods="POST">
<inSequence>
<property name="uri.var.httpendpointurl" expression="$body/root/a" scope="default" type="STRING"/>
<call>
<endpoint>
<http uri-template="{uri.var.httpendpointurl}"/>
</endpoint>
</call>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
We have Apigee passing calls directly to our backend services.
However Apigee seems to remove the headers for Authorization: Bearer
How can I force Apigee to keep Authorization headers and not strip them out
Try to check in your service, in Remove Header Authorization (it is policy that auto created by apigee) you will see the code below:
<Remove>
<Headers>
<Header name="Authorization"/>
<Header name="Accept"/>
<Header name="accept-encoding"/>
<Header name="cache-control"/>
<Header name="cookie"/>
<Header name="Postman-Token"/>
</Headers>
</Remove>
So, you have to remove <Header name="Authorization"/>
Yes Pim, that is correct, just to be more precise while generating a proxy, Apigee will add below Policy code by default-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="remove-header-authorization">
<DisplayName>Remove Header Authorization</DisplayName>
<Remove>
<Headers>
<Header name="Authorization"/>
</Headers>
</Remove>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
I have a Mule flow which uses HTTP Request endpoint in Mule CE3.6.1. It needs to use encoded HTTP url to get the correct data.
Please note the encoded url: /items?q=%2Blabel%3ABOTV2309H*%20%2Bparent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F*&rows=100&start=0
Here is the test flow.
<?xml version="1.0" encoding="UTF-8"?>
<mule 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="CE-3.6.1"
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:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8089" basePath="/" usePersistentConnections="false" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Config_Search" host="testserver" port="80" basePath="/index" usePersistentConnections="false" doc:name="HTTP Request Configuration"/>
<flow name="testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="*" allowedMethods="POST" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<logger level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Config_Search" path="/items?q=%2Blabel%3ABOTV2309H*%20%2Bparent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F*&rows=100&start=0" method="GET" doc:name="HTTP"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
</mule>
When the Mule flow runs, here is the url being requested (Found through wireshark):
/items?q=%20label%3ABOTV2309H%2A%20%20parent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F%2A&rows=100&start=0
Please note %2B is replaced with %20 in two places, which obviously do not return the data I need.
Is this an issue with HTTP endpoint?
Thanks!
I divided the params into query and uri params. Then this issue got resolved.
<http:request config-ref="HTTP_Request_Config_Search" path="/items" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="q" value="+label:BOTV2309H* +parent.uri:\/test\/gateway\/*"/>
<http:uri-param paramName="rows" value="100"/>
<http:uri-param paramName="start" value="0"/>
</http:request-builder>
</http:request>
Here's my policy:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="extract-operation">
<DisplayName>extract-operation</DisplayName>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<Source clearPayload="true">request.content</Source>
<VariablePrefix>apigee</VariablePrefix>
<XMLPayload stopPayloadProcessing="false">
<Namespaces>
<Namespace prefix="soapenv">http://schemas.xmlsoap.org/soap/envelope/</Namespace>
</Namespaces>
<Variable name="operation" type="string">
<XPath>/soapenv:Envelope/soapenv:Body</XPath>
</Variable>
</XMLPayload>
</ExtractVariables>
In trace tool I see that request.content resolves fine and shows the content, but I was expecting apigee.operation to be populated with the contents of . What am I doing wrong?
Fixed Policy:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="extract-operation">
<DisplayName>extract-operation</DisplayName>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<Source clearPayload="true">request.content</Source>
<XMLPayload stopPayloadProcessing="false">
<Namespaces>
<Namespace prefix="soapenv">http://schemas.xmlsoap.org/soap/envelope/</Namespace>
</Namespaces>
<Variable name="operation" type="nodeset">
<XPath>/soapenv:Envelope/soapenv:Body</XPath>
</Variable>
</XMLPayload>
</ExtractVariables>
If you know the Xpath you don't really need the scema and then you take on more variable out of the equation (ie whether the schema is valid). Then you could just reference //Body (or wherever it is in the xml)