Policies
In Azure API Management, you can change API behavior through configuration using policies. Policies are a collection of statements that are run sequentially on the request or response of an API. Read more in the Policies in Azure API Management documentation.
Although you can do quite a lot with policies we recommend that you keep them as simple as possible since we try to follow the principle of smart endpoints and dumb pipes.
Policy files SHOULD
be stored in the repo folder src/bicep/policies
.
Policies are applied at three levels:
- Tenant — IMPORTANT! These policies are enforced centrally and
SHOULD NOT
be set on individual APIs. - API — This policy is set on API level and a basic policy has already been setup. Update the
apiPolicy.xml
located in the repo foldersrc/bicep/policies/
- Operation — Theses policies are applied per operation. Use naming standard
[operationId]-operationPolicy.xml
An operation policy file need to be connected to the API operator in the bicep file api-definition.bicep
located in the repo folder src/bicep/
.
The connection is done using the operationDefinitions array.
param operationDefinitions array = [
{
operationId: '{operation-id}'
policy: loadTextContent('./policies/{policy-file}')
}
{
operationId: '{another-operation-id}'
policy: loadTextContent('./policies/{another-policy-file}')
}
]
In the example below the operation GetSessions is connected with a policy. First, the relevant part of the oas.yaml file:
paths:
/sessions:
get:
tags:
- sessions
description: A list of sessions. Optional parameters work as filters to reduce
the listed sessions.
operationId: GetSessions
And then how to define the operationDefinitions array:
param operationDefinitions array = [
{
operationId: 'GetSessions'
policy: loadTextContent('./policies/getsessions-operationPolicy.xml')
}
]
Ex: getsessions-operationPolicy.xml
with grant type Client Credentials
<policies>
<inbound>
<base />
<cache-lookup-value key="@("api0000-demo-conference-sessions-bearerToken")" variable-name="bearerToken" />
<choose>
<when condition="@(!context.Variables.ContainsKey("bearerToken-sessions"))">
<send-request ignore-error="true" timeout="20" response-variable-name="accessTokenResult" mode="new">
<set-url>{{api0000-demo-conference-sessions-tokenUrl}}</set-url>
<set-method>POST</set-method>
<set-header name="Accept" exists-action="override">
<value>*/*</value>
</set-header>
<set-header name="Accept-Encoding" exists-action="override">
<value>gzip, deflate, br</value>
</set-header>
<set-header name="Content-Type" exists-action="override">
<value>application/x-www-form-urlencoded</value>
</set-header>
<set-body>@{
return "client_id={{api0000-demo-conference-sessions-client-id}}&client_secret={{api0000-demo-conference-sessions-client-secret}}&scope={{api0000-demo-conference-sessions-scope}}&grant_type=client_credentials";
}</set-body>
</send-request>
<set-variable name="accessToken" value="@(((IResponse)context.Variables["accessTokenResult"]).Body.As<JObject>())" />
<set-variable name="bearerToken" value="@((string)((JObject)context.Variables["accessToken"])["access_token"])" />
<set-variable name="tokenDurationSeconds" value="@((int)((JObject)context.Variables["accessToken"])["expires_in"])" />
<cache-store-value key="api0000-demo-conference-sessions-bearerToken" value="@((string)context.Variables["bearerToken"])" duration="@((int)context.Variables["tokenDurationSeconds"])" />
</when>
</choose>
<set-header name="Authorization" exists-action="override">
<value>@("Bearer " + (string)context.Variables["bearerToken"])</value>
</set-header>
<set-backend-service backend-id="api0000-demo-conference-sessions" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
<choose>
<when condition="@(context.Response.StatusCode == 401 || context.Response.StatusCode == 403)">
<cache-remove-value key="api0000-demo-conference-sessions-bearerToken" />
</when>
</choose>
</outbound>
<on-error>
<base />
</on-error>
</policies>
See Azure API Management Policy Snippets for more information about snippets.