Friday Fact: Self-Chained APIM request is possible even if your APIM is configured to use a virtual network

  • Sandro Pereira
  • Dec 27, 2024
  • 4 min read

By default, API Management exposes your instance to the internet through a public endpoint and uses it as a gateway to public backends. However, APIM lets you secure access to your instance and backend APIs by using an Azure virtual network.

Modernize legacy APIs

One of the most powerful features of API Management is its ability to help developers modernize legacy APIs and simplify authentication. For example, many APIs require a token that expires after a few minutes. In these cases, traditional integration processes usually make two separate calls whenever they communicate with the API:

  • The first request is to generate the token.
  • The second is to perform the desired operation.

Even if there are several requests during the period the initial token is alive, those processes simply ignore that capability because it normally requires additional logic to be involved. Some more “smart” processes or applications will store that token in a cache or database, and regenerate it only when it is about to expire or has already expired.

📝 One-Minute Brief

This Friday Fact explains how Azure API Management can perform self‑chained requests even when deployed inside a virtual network. It shows how to call internal APIM operations using policies, enabling scenarios such as token generation, caching, and reuse without adding complex logic to backend services.

Traditional token generation logic

Well, this additional logic can simply be transported to the API Management layer. To accomplish that, you can:

  • Expose an “internal” method, which is token generation. That operation is responsible for checking if there is a Token in the internal APIM Cache. If it exists, return the token from the cache – avoiding an additional call to the API. If not, it will call the API to generate a new token and cache it in the internal APIM cache.
  • Then, on the All Operation, the first thing, or one of the first things, you need to do is to call the “internal” token generation operation to get the token – you should perform this policy in the All operation in order to avoid reimplementing this logic in each operation.

Using the Self-Chained APIM request approach

The main question is, can we implement a Self-Chained APIM request?

The answer is yes, you can. Even if your APIM service is configured to use an Azure virtual network.

You can accomplish this by using the send-request policy. The send-request policy sends the provided request to the specified URL, waiting no longer than the set timeout value.

Policy Statement

<send-request mode="new | copy" response-variable-name="" timeout="60 sec" ignore-error
="false | true">
  <set-url>request URL</set-url>
  <set-method>...</set-method>
  <set-header>...</set-header>
  <set-body>...</set-body>
  <authentication-certificate thumbprint="thumbprint" />
  <proxy>...</proxy>
</send-request>

Of course, you can use the hostname of the backend URL in many cases, but you may run into specific issues if your APIM is configured to use an Azure virtual network. Now, the trick to make this always work is to change the hostname of the backend URL to https://127.0.0.1. A set-header policy should also be added to the send-request policy to add the desired host header (previously used as part of the URL).

Here is an actual sample scenario:

<policies>
    <inbound>
        <send-request ignore-error="false" timeout="60" response-variable-name="tokenResponse" mode="new">
            <set-url>https://127.0.0.1/your-api/tokenrenewal</set-url>
            <set-method>GET</set-method>
            <set-header name="Ocp-Apim-Subscription-Key" exists-action="override">
                <value>@(context.Request.Headers.GetValueOrDefault("Ocp-Apim-Subscription-Key", "Unknown"))</value>
            </set-header>
            <set-header name="Host" exists-action="override">
                <value>your-gateway-host</value>
            </set-header>
        </send-request>
        <set-variable name="tokenValue" value="@(((IResponse)context.Variables["tokenResponse"]).Body.As<string>())" />
        <base />
    </inbound>
    <on-error>
        <base />
    </on-error>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
</policies>

To lazy to read? We’ve got you covered! Check out our video version of this content!

If you liked the content or found it helpful and want to help me write more, you can buy (or help buy) my son a Star Wars Lego set! 

Buy me a coffee
Author: Sandro Pereira

Sandro Pereira lives in Portugal and works as a consultant at DevScope. In the past years, he has been working on implementing Integration scenarios both on-premises and cloud for various clients, each with different scenarios from a technical point of view, size, and criticality, using Microsoft Azure, Microsoft BizTalk Server and different technologies like AS2, EDI, RosettaNet, SAP, TIBCO etc. He is a regular blogger, international speaker, and technical reviewer of several BizTalk books all focused on Integration. He is also the author of the book “BizTalk Mapping Patterns & Best Practices”. He has been awarded MVP since 2011 for his contributions to the integration community.

Leave a Reply

Your email address will not be published. Required fields are marked *

The Ultimate Cloud
Management Platform for Azure

Supercharge your Azure Cost Saving

Learn More
Turbo360 Widget

Back to Top