Use Azure Api Management as a passthrough

2019-04-09 07:25发布

问题:

I would like to create a policy in Azure API Management that forwards all calls that start with the path "proxy/search" to another url. However, i don't want to have to import/create endpoints in APIM for every possibility since this makes it a maintenance nightmare. For example..

  • GET https://whatever.azure-api.net/proxy/search?q=dogs
  • GET https://whatever.azure-api.net/proxy/search/categories?q=dogs
  • GET https://whatever.azure-api.net/proxy/search/categories/x/y/z/etc....?q=blah

to the corresponding...

  • GET https://mysearchapi.com/?q=dogs
  • GET https://mysearchapi.com/categories?q=dogs
  • GET https://mysearchapi.com/categories/x/y/z/etc....?q=blah

I've built the policy below but it looks like APIM wants exact routes to map from it to the backend. I don't want to do this because this proxy may be forwarding to many, many routes apis etc...

<policies>
    <inbound>
        <base />
        <set-variable name="baseUrlSearch" value="https://mysearchapi.com/" />
        <set-variable name="matchSearch" value="proxy/search" />
        <set-variable name="isRoutingComplete" value="false" />
        <set-variable name="apiVersionDefaultSearch" value="1.0" />
        <choose>
            <when condition="@{return context.Request.Url.Path.Contains(context.Variables.GetValueOrDefault<string>("matchSearch"));}">
                <set-backend-service base-url="@(context.Variables.GetValueOrDefault<string>("baseUrlSearch"))" />
                <rewrite-uri template="@(context.Request.Url.Path.Replace(context.Variables.GetValueOrDefault<string>("matchSearch"), ""))" />
                <set-header name="Api-Version" exists-action="skip">
                    <value>@(context.Variables.GetValueOrDefault<string>("apiVersionDefaultSearch"))</value>
                </set-header>
                <set-variable name="isRoutingComplete" value="true" />
            </when>
            <when condition="@(!context.Variables.GetValueOrDefault<bool>("isRoutingComplete"))">
                <return-response>
                    <set-status code="400" reason="Bad Request Through Proxy" />
                </return-response>
            </when>
        </choose>
    </inbound>
    <outbound>
        <base />
    </outbound>
</policies>

回答1:

You are making your life much harder than it needs to be. Simply create an operation that uses /proxy/* as the template and it will match to all the URLs you identified.

Then just create a policy for that operation that does set-backend-service.



回答2:

Adding to Darrel Miller's answer, here is how i got it working...

Adding an operation...

{
  "name": "Search_GET",
  "method": "GET",
  "urlTemplate": "/search/*",
  "policies": null
}       

Adding a policy for that operation...

<policies>
    <inbound>
        <base />
        <set-backend-service base-url="https://mysearchapi.com/" />
        <rewrite-uri template="@(context.Request.Url.Path.Replace("search/", ""))" />
        <set-header name="Api-Version" exists-action="skip">
            <value>1.0</value>
        </set-header>
    </inbound>
    <outbound>
        <base />
    </outbound>
</policies>