Search code examples
azureazure-api-managementapim

Azure API management: Set different backend url for different endpoints


I have an Azure API which have multiple endpoints and it calls different backend service with different api-keys.
Eg:

  1. /offer endpoint in azure apim calls : https://offerBackend/offers
  2. /offer/{id} - https://offerBackend/offers/{id}
  3. /products - https://productBackend/products
  4. /customer - https://customerBackend/customer

I am trying to use set-backend-service based on the endpoint being called, like:

<policies>
    <inbound>
        <base />
        <!-- Start:Set Different backends on basis of endpoints -->
            <when condition="@(context.Request.Url.Path.Contains("offer"))">
                <set-backend-service base-url="https://offerBackend" />
            </when>
            <when condition="@(context.Request.Url.Path.Contains("product"))">
                <set-backend-service base-url="https://productBackend" />
            </when>
            <when condition="@(context.Request.Url.Path.Contains("customer"))">
                <set-backend-service base-url="https://customerBackend" />
            </when>
        <!-- End:Set Different backends on basis of endpoints -->
    </inbound>

But for these different backends I need to pass different credentials i.e. api-key in header.How can I do that?


Solution

  • The when elements do not have the parent element choose.
    Example:

    <choose>
        <when condition="Boolean expression | Boolean constant">
            <!— one or more policy statements to be applied if the above condition is true  -->
        </when>
        <when condition="Boolean expression | Boolean constant">
            <!— one or more policy statements to be applied if the above condition is true  -->
        </when>
        <otherwise>
            <!— one or more policy statements to be applied if none of the above conditions are true  -->
        </otherwise>
    </choose>
    

    You can specify the api-keys as named values to store them as secrets:

    enter image description here

    The named value can be used as header value for authentication to the backend:

    <set-header name="api-key" exists-action="override">
       <value>{{offer-api-key}}</value>
    </set-header>
    <set-backend-service base-url="https://offerBackend" />
    

    The complete policy:

    <policies>
        <inbound>
            <base />
            <!-- Start:Set Different backends on basis of endpoints -->
            <choose>
                <when condition="@(context.Request.Url.Path.Contains("offer"))">
                    <set-header name="api-key" exists-action="override">
                        <value>{{offer-api-key}}</value>
                    </set-header>
                    <set-backend-service base-url="https://offerBackend" />
                </when>
                <when condition="@(context.Request.Url.Path.Contains("product"))">
                    <set-header name="api-key" exists-action="override">
                        <value>{{product-api-key}}</value>
                    </set-header>
                    <set-backend-service base-url="https://productBackend" />
                </when>
                <when condition="@(context.Request.Url.Path.Contains("customer"))">
                    <set-header name="api-key" exists-action="override">
                        <value>{{customer-api-key}}</value>
                    </set-header>
                    <set-backend-service base-url="https://customerBackend" />
                </when>
            </choose>
            <!-- End:Set Different backends on basis of endpoints -->
        </inbound>
    

    A different solution is, to use backends and configure URL, authentication, ... in one place:

    enter image description here

    This can be used in the set-backend-service policy

    <when condition="@(context.Request.Url.Path.Contains("offer"))">
          <set-backend-service backend-id="Offer" />
    </when>
    

    The complete inbound policy with Backend-Ids:

    <policies>
        <inbound>
            <base />
            <!-- Start:Set Different backends on basis of endpoints -->
            <choose>
                <when condition="@(context.Request.Url.Path.Contains("offer"))">
                    <set-backend-service backend-id="Offer" />
                </when>
                <when condition="@(context.Request.Url.Path.Contains("product"))">
                    <set-backend-service backend-id="Product" />
                </when>
                <when condition="@(context.Request.Url.Path.Contains("customer"))">
                    <set-backend-service backend-id="Customer" />
                </when>
            </choose>
            <!-- End:Set Different backends on basis of endpoints -->
        </inbound>