My requirement is fairly simple. I have an APIM endpoint that calls a backend HTTP service with a predefined timeout. If the request times out or returns an error other than 'Bad Request' (Status Code > 400)
, the call needs to be retried with a fail-over HTTP service until success or utmost 5 times. I am trying to come with an APIM policy to accomplish this. While the retry and fail-over works if the returned status code is above 400, it doesn't happen if the request simply times out. If the request simply times out, the control doesn't even enter the <retry>
block. I am fairly certain the retry condition I put in is not being capable to capture the time out condition. Could someone help me figure out the APIM policy to be used to record timeouts?
Below is the APIM policy.
<policies>
<inbound>
<base />
<set-variable name="isFlag" value="true" />
</inbound>
<backend>
<choose>
<when condition="@(context.Variables.GetValueOrDefault<string>("isFlag") == "true")">
<set-backend-service base-url="<primary url>" />
<forward-request timeout="5" />
<retry condition="@(context.Response == null || context.Response.StatusCode > 400)" count="5" interval="1" first-fast-retry="true">
<set-backend-service base-url="<secondary url>" />
</retry>
</when>
</choose>
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Below is the excerpt from the APIM trace
Inbound
(3.014 ms)
api-inspector (0.403 ms)
{
"request": {
"method": "GET",
"url": "https://gpcshare-apim-gpc-dev-aes.azure-api.net/statcode/405?sleep=7000",
"headers": [
{
"name": "Ocp-Apim-Subscription-Key",
"value": "a02f7f4e18d54d84ba55d4f122548072"
},
{
"name": "Sec-Fetch-Site",
"value": "cross-site"
},
{
"name": "Sec-Fetch-Mode",
"value": "cors"
},
{
"name": "X-Forwarded-For",
"value": "103.111.183.78"
},
{
"name": "Cache-Control",
"value": "no-cache, no-store"
},
{
"name": "Via",
"value": "ICAP/1.0 bmg70302.ibosscloud.com (IBOSS/0.4.4 iboss ICAP service )"
},
{
"name": "Content-Type",
"value": "text/plain;charset=UTF-8"
},
{
"name": "Accept",
"value": "*/*"
},
{
"name": "Accept-Encoding",
"value": "gzip,deflate,br"
},
{
"name": "Accept-Language",
"value": "en-US,en;q=0.9"
},
{
"name": "Host",
"value": "gpcshare-apim-gpc-dev-aes.azure-api.net"
},
{
"name": "Referer",
"value": "https://apimanagement.hosting.portal.azure.net/apimanagement/Content/1.42.0.1/apimap//apimap-apis/index.html?clientOptimizations=undefined&l=en.en-us&trustedAuthority=https%3A%2F%2Fportal.azure.com&shellVersion=undefined"
}
]
}
}
api-inspector (0.004 ms)
{
"configuration": {
"api": {
"from": "/statcode",
"to": null,
"version": null,
"revision": "1"
},
"operation": {
"method": "GET",
"uriTemplate": "/{code}"
},
"user": "-",
"product": "-"
}
}
cors (2.601 ms)
"Origin header was missing or empty and the request was classified as not cross-domain. CORS policy was not applied."
cors (0.002 ms)
"Origin header was missing or empty and the request was classified as not cross-domain. CORS policy was not applied."
set-variable (0.003 ms)
{
"message": "Context variable was successfully set.",
"name": "isFlag",
"value": "true"
}
Backend
(4,991.587 ms)↑ Back to top
choose (0.017 ms)
{
"message": "Expression was successfully evaluated.",
"expression": "context.Variables.GetValueOrDefault<string>(\"isFlag\") == \"true\"",
"value": true
}
set-backend-service (0.007 ms)
{
"message": "Backend service URL was changed.",
"oldBackendServiceUrl": "",
"newBackendServiceUrl": "https://httpstat.us/",
"request": {
"url": "https://httpstat.us/405?sleep=7000"
}
}
forward-request (0.151 ms)
{
"message": "Request is being forwarded to the backend service. Timeout set to 5 seconds",
"request": {
"method": "GET",
"url": "https://httpstat.us/405?sleep=7000",
"headers": [
{
"name": "Host",
"value": "httpstat.us"
},
{
"name": "Request-Id",
"value": "|f595c50c66d7453c97a7dc14c9c1af9e.2b06f656cb6c4704_b907aebb."
},
{
"name": "Ocp-Apim-Subscription-Key",
"value": "a02f7f4e18d54d84ba55d4f122548072"
},
{
"name": "Sec-Fetch-Site",
"value": "cross-site"
},
{
"name": "Sec-Fetch-Mode",
"value": "cors"
},
{
"name": "X-Forwarded-For",
"value": "103.111.183.78,13.91.254.72"
},
{
"name": "Cache-Control",
"value": "no-cache, no-store"
},
{
"name": "Via",
"value": "ICAP/1.0 bmg70302.ibosscloud.com (IBOSS/0.4.4 iboss ICAP service )"
},
{
"name": "Content-Type",
"value": "text/plain;charset=UTF-8"
},
{
"name": "Accept",
"value": "*/*"
},
{
"name": "Accept-Encoding",
"value": "gzip,deflate,br"
},
{
"name": "Accept-Language",
"value": "en-US,en;q=0.9"
},
{
"name": "Referer",
"value": "https://apimanagement.hosting.portal.azure.net/apimanagement/Content/1.42.0.1/apimap//apimap-apis/index.html?clientOptimizations=undefined&l=en.en-us&trustedAuthority=https%3A%2F%2Fportal.azure.com&shellVersion=undefined"
}
]
}
}
forward-request (4,991.413 ms)
{
"messages": [
"Error occured while calling backend service.",
"Request to the backend service timed out"
]
}
Outbound
(0.183 ms)↑ Back to top
transfer-response (0.067 ms)
{
"message": "Response headers have been sent to the caller."
}
transfer-response (0.116 ms)
{
"message": "Response body streaming to the caller is complete."
}