When setting the rate-limit I apply to All Operations does it sum ALL endpoint calls together or is this rate limit per endpoint? This is crucial info when calculating a baseline for the maximum nr of calls, but I'm afraid I can't find any information in Azure itself about how this works...
Here is the policy I want to add to All Operations:
<rate-limit-by-key />
Then in my endpoint I want to just inherit by adding:
<base />
As it stands the calls under All operations get summed up in a single queue. So the rate limit counter is not for individual endpoints, not even if it is applied directly to an individual endpoint the reason being that the key is not unique to that enpoint.
So a call coming from one IP adress to different endpoints under the same inbound rule for example will update the counter for all enpoints using the same key (in this case the IP address).
To circumvent this I've made my keys unique by chaining IP address and operation name together forming a queue per endpoint and adding <rate-limit-by-key> to my endpoint instead of the <base />
The finished example inbound rule on my endpoint:
<rate-limit-by-key calls="xx" renewal-period="xx" counter-key="#(string.Join("-", context.Request.IpAddress, context.Operation.Id))" />
During request processing policies are executed sequentially. tag on lower level policies defines when upper level policies are executed. rate-limit-by-key works by maintaining one counter per provided key value irrelevant of where it's placed. If this counter goes over limits specified in policy request is blocked.
In other words, two rate-limit-by-key policies placed in different scopes will share counter value, but not limits.
Related
I am having difficulty adding text into my url path between my frontend and backend when using Azure Api Management.
I have a Azure functions api with a url like this:
e.g. https://pXXXXX-myapi.azurewebsites.net/api/pXXXXX/alm/{name}
The default api created by Azure API Management is this:
e.g. https://myapi.azure-api.net/pXXXXX/pXXXXX/alm/{name}
Ideally I'd like to Frontend to remove the redundant pXXXXX:
e.g. https://myapi.azure-api.net/pXXXXX/alm/{name}
If I remove it from the front end e.g. GET /pXXXXX/alm/{name} becomes GET /alm/{name}.
Then I receive a 500 error.
I assume this is because removing "/pXXXXX" removes it from the backend path as well.
So I have tried to use the rewrite-uri policy like so:
<rewrite-uri template="/pXXXXX/alm/{name}" copy-unmatched-params="false" />
I've tried multiple variations of this with no success.
Assuming
you've changed the frontend for your operation to "GET /alm/{name}"
and your backend function app service url is "https://pXXXXX-myapi.azurewebsites.net/api"
and your API Base URL is "https://myapi.azure-api.net/pXXXXX"
then rewrite-uri exactly like you pasted is correct. You want to add leading "pXXXXX" to the url.
I've reproduced exact same scenario on my side and it works.
500 error does not mean there is something wrong with the path. If you would wrongly configure your url you would get 404. Most probably there is an internal error inside your function app or other policies in the APIM. Just call this API with Ocp-Apim-Trace header set to true and subscription key that allows tracing and you will see what is wrong. Or you can paste trace here if you want so we can help.
Posting my own answer but thanks to those who tried to help.
I believe the issue came from an error from APIM itself.
I assume it was not setting up the policies correctly, because now it is automatically including set-backend-service in the inbound policy whereas it did not over the past 2 days when I have been repeatably re-creating my api.
Now my inbound policy looks like this:
<inbound>
<base />
<set-backend-service id="apim-generated-policy" backend-id="pXXXXX-myapi" />
<rewrite-uri template="/pXXXXX/alm/{name}" copy-unmatched-params="false" />
</inbound>
And my front end api looks as before:
/pXXXXX/alm/{name}
I am trying to create a policy in APIM which fetches the product for the subscription-key passed in the header. I need to get that product name and do set-header with that name for the backend service. Is it possible to achieve it through APIM Policies ?
First, we added two more subscription scopes: all APIs and a single API. The scope of subscriptions is no longer limited to an API product. It's now possible to create keys that grant access to an API, or all APIs within an API Management instance, without needing to create a product and add the APIs to it first. Also, each API Management instance now comes with an immutable, all-APIs subscription. This subscription makes it easier and more straightforward to test and debug APIs within the test console.
You can get the Product Name with #(context.Product.Name).
<inbound>
<base />
<set-variable name="aaa" value="#(context.Product.Name)" />
<set-body template="liquid">
{
"success": true,
"var1": {{context.Variables["aaa"]}}
}
</set-body>
</inbound>
In test, set the product name as Starter and you will get the snapshot as below.
Is it possible to do a short polling internally in an APIM request then respond with sync response?
The flow goes like this:
1. APIM receives a request
2. APIM triggers a durable function orchestration.
3. APIM waits and polls the durable function response (through a policy?)
4. APIM responds with the actual result
To the API Consumer, it will be a single request.
Is this a common pattern? Or is it better to just provide the 202 Response polling URL to the API consumer? I'm expecting the request to take only around a few seconds to under a minute.
Is there a more standard way of doing this that I haven't considered yet?
It is subjective to how you want your API to be presented to the consumers.
If you want the front end users to poll the API then 202 Accepted response with a polling url in location header is the way.
If you want to disguise your API as a synchronous API , you will have to implement the polling pattern itself inside the APIM policy. For this refer following post
Use API-M To Mask Async APIs When Moving Implementation to Logic Apps, even though it pertains to logic app, you can implement the same pattern for any async API
excerpt from the link:
<outbound>
<base />
<retry condition="#(((IResponse)context.Variables["var"]).StatusCode == 202)" count="10" interval="30">
<send-request mode="new" response-variable-name="var" ignore-error="false">
<set-url>#(context.Response.Headers["location"][0])</set-url>
<set-method>GET</set-method>
</send-request>
</retry>
<return-response response-variable-name="var" />
</outbound>
As I pointed out earlier, it really depends upon how you want your API to be presented to your consumers. Both patterns are valid.
I want to record the timings for the backend web service being fronted by the API Management service. We front a few 3rd party services so the only way we can get performance data is to log the backend request before and after. My plan was to utilise the base policy (All APIs / All Operations) like this
<backend>
<!-- log start of request -->
<forward-request />
<!-- log end of request -->
</backend>
But trying this I get;
Error in element 'backend' on line XX, column XX: backend section
allows only one policy to be specified
Can you have any policy expressions in the backend element?
backend section is very limited in what policies are allowed there. Your best option would be to do your logging last thing in inbound and first thing in outbound. You can control what policy is executed first by moving "base" tag to a desired position, it effectively controls when (and if) upper level policies are executed.
You can use Log to EventHub in this case to log whatever you want for a given request (which has Id you can use as correlation id).
Is there any reason to use an outbound policy in APIM? I tried a test where I used the same policy expression for inbound as well as outbound. The same expression worked without error and returned the same info for both. I don't see any need to configure an outbound policy if an inbound expression already captures all of the information. Have you also found the outbound section to be redundant and simply excluded the outbound section? Or have you found any reason to use the outbound section in addition to the inbound section?
Outbound policies can be used to manipulate/inspect a response body or headers returned from a backend API.
Examples of things you might do in an outbound policy:
Set the cache duration based on the Cache-Control header returned from the API
Remove headers created by the API framework like X-Powered-By and X-Aspnet-Version
Calculate an etag value using a checksum of the body
Create a signature header to prevent tampering with a response body
Update the returned response body with cached fragments
Log the returned response to a diagnostic system or audit trail