I am working on APIM caching and while testing. I found caching not working. If below header or query parameters (userAuthorizationToken,ProductCode, PageNo, Limit) remain same it should return cache response.
I am using postman to test the endpoint by calling "GetProduct" passing parameters. then I enter more records in database and call the Getproduct again it return more records. However, caching duration not met.
Any advice.
<policies>
<inbound>
<base />
<cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none" must-revalidate="true" allow-private-response-caching="true" caching-type="internal" >
<vary-by-header>userAuthorizationToken</vary-by-header>
<vary-by-query-parameter>productCode</vary-by-query-parameter>
<vary-by-query-parameter>pageNo</vary-by-query-parameter>
<vary-by-query-parameter>limit</vary-by-query-parameter>
</cache-lookup>
</inbound>
<backend>
<base/>
</backend>
<outbound>
<cache-store duration="2400" />
<base/>
</outbound>
<on-error> ....etc
Unfortunately, I can't access APIM in azure portal.
Related
I've configured an API Management policy to retry to a second region if the first encounters an error.
However, when I disable the primary function app, based in Sydney, there are no retries recorded in Application insights - only the original failing request. There are no function calls recorded in the Melbourne function app.
I've tried a bunch of different configurations. Both region function apps are running fine.
I've got the copied the code below, is there something that I'm missing or not understanding?
Thanks in advance
API Policy
<policies>
<inbound>
<base />
<choose>
<when condition="#(context.Variables.GetValueOrDefault<int>('RetryCounter', 0) == 0)">
<set-backend-service base-url="{{syndey-function-app}}" />
</when>
<otherwise>
<set-backend-service base-url="{{melbourne-function-app}}" />
</otherwise>
</choose>
</inbound>
<backend>
<retry count="1" interval="0" first-fast-retry="true" condition="#(
context.Response.StatusCode > 400
)">
<set-variable name="RetryCounter" value="#(context.Variables.GetValueOrDefault<int>('RetryCounter', 0) + 1)" />
<forward-request buffer-request-body="true" timeout="15"/>
</retry>
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
403 Error Response
<h1 id="unavailable">Error 403 - This web app is stopped.</h1>
<p id="tryAgain">
The web app you have attempted to reach is currently stopped and does not
accept any requests. Please try to reload the page or visit it again soon.
</p>
<p id="toAdmin">
If you are the web app administrator, please find the common 403 error
scenarios and resolution <a href="https://go.microsoft.com/fwlink/?linkid=2095007"
target="_blank">here</a>. For further troubleshooting tools and recommendations,
please visit Azure Portal.
</p>
I had to replace the single quotes to double quotes because of an error on save:
context.Variables.GetValueOrDefault<int>('RetryCounter', 0) => context.Variables.GetValueOrDefault<int>("RetryCounter", 0)
For testing I created two mocked services:
Returns status code 200:
https://rfqapiservicey27itmeb4cf7q.azure-api.net/echo/200/test
Returns status code 403:
https://rfqapiservicey27itmeb4cf7q.azure-api.net/echo/403/test
The retry section in the backend section will never return to the inbound section. So the choose condition was only hit at the very beginning.
Therefore, the choose condition has to be moved to the backend section.
<policies>
<inbound>
<base />
<set-backend-service base-url="https://rfqapiservicey27itmeb4cf7q.azure-api.net/echo/403" />
<!--
<set-backend-service base-url="{{syndey-function-app}}" />
-->
</inbound>
<backend>
<retry count="1" interval="0" first-fast-retry="true" condition="#(
context.Response.StatusCode > 400
)">
<set-variable name="RetryCounter" value="#(context.Variables.GetValueOrDefault<int>("RetryCounter", 0) + 1)" />
<choose>
<when condition="#(context.Variables.GetValueOrDefault<int>("RetryCounter", 0) > 1)">
<set-backend-service base-url="https://rfqapiservicey27itmeb4cf7q.azure-api.net/echo/200" />
<!--
<set-backend-service base-url="{{melbourne-function-app}}" />
-->
</when>
</choose>
<forward-request buffer-request-body="true" timeout="15" />
</retry>
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
My sample operation executes as expected:
https://rfqapiservicey27itmeb4cf7q.azure-api.net/sample/test
The first hit in the backend requests the 403 resource:
This request is failing, and the retry policy sets the 200 in the backend section:
This second request is successful when will return 200 and leave the backend section:
I have been trying to change the cookie path of my Azure APIM API response. The response from the APIM looks like this Set-Cookie: ssnid=2d4cfdd62638436481130eb0fad7a889; path=/; secure; HttpOnly. I checked the transform policies available here but still haven't figured out a solution.
I haven't run this but this should generally work:
<policies>
<inbound>
<base />
</inbound>
<backend>
<base />
</backend>
<outbound>
<set-header name="Set-Cookie" exists-action="override">
<value>#{
var cookie = context.Response.Headers.GetValueOrDefault("Set-Cookie","");
return cookie.Replace("path=/;", "path=/myNewPath;");
}
</value>
</set-header>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
How to prevent large file requests using Azure APIM?
Example: Block any POST request having file size > 50MB
You can apply the following policy for all your APIs. For each POST request, the policy will check the body size, and if the size is above 50MB, it will return status 413 - Payload Too Large.
<policies>
<inbound>
<base />
<choose>
<when condition="#(context.Request.Method == "POST")">
<set-variable name="bodySize" value="#(context.Request.Headers["Content-Length"][0])" />
<choose>
<when condition="#(int.Parse(context.Variables.GetValueOrDefault<string>("bodySize"))<52428800)">
<!--let it pass through by doing nothing-->
</when>
<otherwise>
<return-response>
<set-status code="413" reason="Payload Too Large" />
<set-body>#{
return "Maximum allowed size for the POST requests is 52428800 bytes (50 MB). This request has size of "+ context.Variables.GetValueOrDefault<string>("bodySize") +" bytes";
}
</set-body>
</return-response>
</otherwise>
</choose>
</when>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
There are policies called quota-by-Key and quota-by-subscription , which will help the users to block the calls that exceed the bandwidth specified. Please verify this link for more details.enter link description here
I already have checked other solutions available on the forum and this one too
REST API service when called from azure APIM returning empty response body with Status code 200
I'm trying to call an authentication service which returns status codes (200,401 and 404)
If it returns 200 then I want my request to be forwarded to the backend otherwise return only status code back to the client.
This is what I added in my policy
<policies>
<inbound>
<base />
<check-header name="username" failed-check-httpcode="401" failed-check-error-message="unauthorised" ignore-case="true" />
<cors>
<allowed-origins>
<origin>*</origin>
</allowed-origins>
<allowed-methods>
<method>GET</method>
<method>POST</method>
</allowed-methods>
</cors>
<send-request mode="new" response-variable-name="receivedResp" timeout="20" ignore-error="true">
<set-url>https://authenticate1.azurewebsites.net/auth</set-url>
<set-method>GET</set-method>
<set-header name="username" exists-action="override">
<value>#(context.Request.Headers.GetValueOrDefault("username",""))</value>
</set-header>
<set-body />
</send-request>
<return-response response-variable-name="receivedResp" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
Now problem is return is returning received response in all cases, when i added a conditional policy i still was not able to return response received from backend.
Can anyone tell how to check status code and return response received from the server in case of 200 only?
The <send-request/> policy returns the response variable of type context.Response. So you can use the methods and variables available for that object. See the below reference to find it.
https://learn.microsoft.com/en-us/azure/api-management/api-management-policy-expressions#ref-context-response
In your case, you can add <choose/> policy and test the
receivedResp.StatusCode != 200. Then you can return based on the response.
Hope it helps
As part of the inbound request I want to assess which format the data has been posted in as so I can convert from one to another. Using I am trying to get the content type;
string contentType = context.Request.Headers.GetValueOrDefault("Content-Type", "text/plain");
I was getting the default value (text/plain) no matter what I set the Content-Type in the request. I recorded the headers to see what was being set and it appears that the inbound policy does get the Content-Type header. Weird that you can set but not retrieve it.
How do I determine what format I have been sent?
It's working with your provided code:
Content-Type: application\json
The complete policy:
<policies>
<inbound>
<base />
<set-body template="none">#{
string contentType = context.Request.Headers.GetValueOrDefault("Content-Type", "text/plain");
return contentType;
}</set-body>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>