'vary' in APIM caching policies - azure

I am learning Apim policies.
In caching policies there is many elements of <vary-by....
In description of microsoft docs, it is mentionned that it caches by for example developer, query parameter...
What does it mean exactly?
Does this have a relation to refreshing values?

I guess you are referring to https://learn.microsoft.com/en-us/azure/api-management/api-management-caching-policies#GetFromCache
<cache-lookup vary-by-developer="true | false" vary-by-developer-groups="true | false" caching-type="prefer-external | external | internal" downstream-caching-type="none | private | public" must-revalidate="true | false" allow-private-response-caching="#(expression to evaluate)">
<vary-by-header>Accept</vary-by-header>
<!-- should be present in most cases -->
<vary-by-header>Accept-Charset</vary-by-header>
<!-- should be present in most cases -->
<vary-by-header>Authorization</vary-by-header>
<!-- should be present when allow-private-response-caching is "true"-->
<vary-by-header>header name</vary-by-header>
<!-- optional, can repeated several times -->
<vary-by-query-parameter>parameter name</vary-by-query-parameter>
<!-- optional, can repeated several times -->
</cache-lookup>
By default the cache lookup would only use the URL path as a reference (the cache key) to find the cached item.
If you however wanted also to vary the cache lookup depending on a certain header or query parameter - with that extending the cache key - you would use <vary-by-header> or <vary-by-query-parameter> - so that for the same URL path responses are cached based on additional header and/or query parameters.
vary-by-developer or vary-by-developer-groups would extend the cache key with user or the group of the user assigned to the subscription key used - so that for the same URL path responses are cached based on who is calling the API operation.

Related

Azure resource graph returns null for a config while the same is present in Json view of resource

While running the below query I get null on internalDomainNameSuffix, but the same has value on Json view from the resource page overview.
resources | where type == 'microsoft.network/networkinterfaces' and name == 'interface1'| project name, properties.dnsSettings.internalDomainNameSuffix
The query result shows correct data for a few resources, but shows null in others while it still shows data through the Json view (It is inconsistent, shows data for some resources but not for others).
Try this:
resources
| where type == 'microsoft.network/networkinterfaces'
| where isnotnull(name) and isnotnull(properties.dnsSettings.internalDomainNameSuffix)
| project name, properties.dnsSettings.internalDomainNameSuffix , resourceGroup
Thanks for your suggestions all.
After few conversations with msft, the conclusion is that at specific scenarios involving VM/Network Interface the resource manager is not updated with the property internalDomainNameSuffix along with other properties.
Workaround suggested is: Any operation performed on the resource will force update the resource manager which in-turn updates all the properties. Just a simple tag update does this as well.
Reg fix: Msft understands this behaviour but does not have any plans on fixing it anytime in the near future or ever.

Read Named values from the context in Azure Apim

I'm defining a inbound policy and trying to construct a URL from 2 components. I know how to get these values 1 but 1 but when I have to combine them into one cant figure out the syntax.
First I call a api and save the response
<send-request mode="copy" response-variable-name="createdUser" timeout="20" ignore-error="false">
<set-url>{{Systems.One.Endpoint}}/services/rest</set-url>
</send-request>
I can trace my response is ok like this
<trace source="Contact Id">#(((IResponse)context.Variables["createdUser"]).Body.As<JObject>()["contactId"])</trace>
But I dont know how to create a url from the {{System.One.Endpoint}} and the #(((IResponse)context.Variables["createdUser"]).Body.As()["contactId"])
This here does not work
<send-request mode="copy" response-variable-name="createPeriod" timeout="seconds" ignore-error="true">
<set-url>
{{System.Two.Endpoint}}/api/#(((IResponse)context.Variables["createPeriod"]).Body.As<JObject>()["contactId"])/createperiod/{{DefaultPeriodlength}}
</set-url>
Everything after the # is just being set as string and not loaded from the actual value form the variable
How can I combine these two values?
Policy expressions can only be used to produce whole value for element/attribute. Named values in contract can be used to represent any part of any attribute/element value, and are inserted into policy prior to it being analyzed/executed.So something like this:
<set-url>#("{{System.Two.Endpoint}}/api/" + ((IResponse)context.Variables["createPeriod"]).Body.As<JObject>()["contactId"].ToString() + "/createperiod/{{DefaultPeriodlength}}")</set-url>
or if you prefer string interpolation:
<set-url>#($"{{System.Two.Endpoint}}/api/{((IResponse)context.Variables["createPeriod"]).Body.As<JObject>()["contactId"]}/createperiod/{{DefaultPeriodlength}}")</set-url>

Check whether or not a query parameter is set

In Azure API Management, I need to check whether or not a query parameter is set. To achieve this, I'm trying to use context.Request.Url.Query.GetValueOrDefault(queryParameterName: string, defaultValue: string).
According to the documentation, this expression works as follows -
Returns comma separated query parameter values or defaultValue if the parameter is not found.
With that in mind, I used the example from the MS blog Policy Expressions in Azure API Management, to create the following <inbound> policy -
<set-variable name="uniqueId" value="#(context.Request.Url.Query.GetValueOrDefault("uniqueId", ""))" />
However, whenever I include this policy, execution fails with 404 Resource Not Found. Upon inspection of the trace, I can see that the execution was aborted without error before a single policy was evaluated (no matter where within <inbound> the above policy is placed.
This behavour results in the following <backend> trace, which explains the 404
"backend": [
{
"source": "configuration",
"timestamp": "2017-09-07T12:42:13.8974772Z",
"elapsed": "00:00:00.0003536",
"data": {
"message": "Unable to identify Api or Operation for this request. Responding to the caller with 404 Resource Not Found."
}
}
],
Given that the MS documentation seems to be inaccurate, how can I check whether or not a query parameter is set?
So the answer here is that there is (another) MS bug.
When the API operation was originally created, the uniqueId query parameter was set as required. I changed this so that it was not required before adding the policy described in my question, however a bug within the new Azure Portal means that when you uncheck the Required box adjacent to the query parameter and then save your changes, they are ignored.
I was able to work around this behaviour be editng the YAML template in the OpenAPPI specification view, removing the declaration required: true for the query parameter in question. The expresion within my policy now works as expected.
Please note: that this workaround sheds light on yet another bug, where saving the template results in your policies being deleted, so make sure you take a copy first.

Azure Rest Api List container : Parameter Marker

Hi Guys I am building a Client which Interact with Azure Storage Rest API.
I was going through documentation https://learn.microsoft.com/ru-ru/rest/api/storageservices/fileservices/list-containers2:
And didn't understood the use of parameter prefix and marker which can be send along with Azure request.
It says:
prefix
Optional. Filters the results to return only containers whose name
begins with the specified prefix.
marker
Optional. A string value that identifies the portion of the list of
containers to be returned with the next listing operation. The
operation returns the NextMarker value within the response body if the
listing operation did not return all containers remaining to be listed
with the current page. The NextMarker value can be used as the value
for the marker parameter in a subsequent call to request the next page
of list items.
The marker value is opaque to the client.
With Prefix, I think:
If i have dir structure:
file01.txt
images/image01.jpg
images/folder/image001.jpg
fightVideo/subFolder/current/video001.mpg
fightVideo/subFolder/current/video002.mpg
If I give prefix container name as "fight". It should return
fightVideo.
But I am not sure.
And for Marker I don't understand whats its use?
Please can someone explain the use of Prefix and Marker with examples?
In context of listing containers, if you specify prefix parameter it will list the containers names of which start with that prefix value. It has nothing to do with listing blobs.
List blobs operation also supports this prefix parameter and when you specify this parameter, it will list the blobs names of which start with that prefix value.
So the example you have given is for listing blobs and when you specify flight as prefix there, you will get back fightVideo/subFolder/current/video001.mpg and fightVideo/subFolder/current/video002.mpg in response but not when you call list containers with this prefix.
Regarding marker, Kalyan's explanation is correct but let me add a little bit more to that.
Essentially Azure Storage Service is a shared service and you simply can't ask it to return all the results in one go (if we were to take an analogy from SQL world, you simply can't do SELECT * FROM TABLE kind of thing). Each request to the service is assigned a predefined timeout and the response would include the items fetched in that time + optionally a token if the service thinks that there's more data available. This token is called continuation token. In order to get the next set of items, you would need to pass this continuation token in the marker parameter in your next request.
Each call to storage service will try to return a predefined maximum number of items. For listing blob containers/blobs, this limit is 5000 items. For listing tables/entities, this limit is 1000 items. If there are more items in your account, then apart from this data storage service returns you a continuation token which tells you that there's more data available.
Please note that even though the limit is there but you can't always assume that you will get these number of records. Based on a number of conditions, it is quite possible that you don't get back any data but still receive a continuation token. So your code need to handle this condition as well.
If there are too many blobs to be listed, then the response contains the NextMarker element.
<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults ServiceEndpoint="https://myaccount.blob.core.windows.net">
<Prefix>string-value</Prefix>
<Marker>string-value</Marker>
<MaxResults>int-value</MaxResults>
<Containers>
<Container>
<Name>container-name</Name>
<Properties>
<Last-Modified>date/time-value</Last-Modified>
<Etag>etag</Etag>
<LeaseStatus>locked | unlocked</LeaseStatus>
<LeaseState>available | leased | expired | breaking | broken</LeaseState>
<LeaseDuration>infinite | fixed</LeaseDuration>
<PublicAccess>container | blob</PublicAccess>
</Properties>
<Metadata>
<metadata-name>value</metadata-name>
</Metadata>
</Container>
</Containers>
<NextMarker>marker-value</NextMarker>
</EnumerationResults>
The REST API documentation mentions that the marker value can be used in a subsequent call to request the next set of list items.
You can imagine marker as a paginatator index.

How do I access a route parameter in Azure API Management

Query string parameter
I have seen plenty of examples of reading query string parameters.
For example take the following URI:
/api/Profile?id={accountId}
The accountId can be read in the policy xml using the following syntax:
context.Request.Url.Query["accountId"]
Route parameter
But what if my URI is structured as:
/api/profiles/{accountId}
How do I read accountId in the policy xml when the parameter is not in the query string?
Using the example above I can read the accountId by the following syntax:
context.Request.MatchedParameters["accountId"]
For example I could assign it to a variable for usage elsewhere in the APIM policy file:
<set-variable name="account-id" value="#(context.Request.MatchedParameters["accountId"])" />
There isn't a massive amount of documentation about it, but thankfully there is at least some mention of the Context variable on learn.microsoft.com.
There is a GitHub repository with quite some snippets including your use case: https://github.com/Azure/api-management-policy-snippets/blob/master/policy-expressions/README.md
For your concrete example, you can use this:
context.Request.MatchedParameters.GetValueOrDefault("accountId", "optional-default-value")
The benefit compared to the other solution is that the policy evaluation does not fail if the URI parameter does not exist. It will use the default value as a fallback instead. Otherwise a 500 Internal Server Error would be returned.

Resources