Policies are a very powerful component in Azure API Management (APIM) that allows to customize API input and output. By using policies in APIM it’s possible, for example:
– Set call rate limits and quotas
– Modify request/response bodies
– Add/remove HTTP headers
– Validate JWT
– Configure CORS
and so on.
Most policies could be applied to:
– Global scope (i.e. everything for this instance of APIM)
– API (APIM instance may host multiple APIs)
– API Operation
– Product
– Or a combination of API, operation and product
However, not every policy SHOULD be applied to any scope.
For example, let’s consider CORS (Cross-Origin Resource Sharing) policy. Setting CORS policy allows API publisher to control which request origins are allowed to call API. By default, Javascript running on a web page from different origin than API (i.e. loaded from different domain) is not allowed to make AJAX calls to API. Setting CORS policy would allow Javascript to make API calls which is essential for building browser-based single page web applications.
Let’s try to add CORS policy to global scope, which should make all of my APIs available for cross-origin calls.
And now let’s try to call API from Javascript:
<!DOCTYPE html> <html> <head> <title>JSSample</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> </head> <p id="message"></p> <body> <script type="text/javascript"> $(function() { $('#message').text('Querying event 1...'); $.ajax({ url: "https://myapi.azure-api.net/v1.0/events/1", beforeSend: function(xhrObj){ // Request headers xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","<sub key>"); }, type: "GET", crossDomain: true }) .done(function(data) { $('#message').html($('#message').text() + '<br>Received:<br>' + JSON.stringify(data)); }) .fail(function(err, textStatus) { $('#message').html($('#message').text() + "<br>error " + JSON.stringify(err) + " " + textStatus); }); }); </script> </body> </html>
That didn’t work out though… We now getting the following error message: “XMLHttpRequest cannot load https://myapi.azure-api.net/v1.0/events/1. Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:4412’ is therefore not allowed access. The response had HTTP status code 404.”
Now, let’s set the same CORS policy in API scope:
That worked out just fine. AJAX call is succeeding.
So, CORS policy should be set only in API or operation scope. Setting it in global scope doesn’t take any effect.
That’s interesting that some other policies are clearly limited to specific scopes in APIM portal. For example, as you can see on the picture above “allow cross domain calls” policy is grayed-out in API scope because it’s only available in global. Sadly, CORS policy could potentially be set in global scope where it doesn’t work.