How to add custom header in Azure API Management before making a call to the backend - azure

I have an Rest Api that is being exposed on Azure. The Azure Api once called calls a WCF Service in the backend.
Firstly I need to transform the JSON Request to XML. Also, To call the SOAP Service I need to add a Custom Header like this:-
<s:Header>
<AuthHeader xmlns="http://abc.security.service">
<UserID>UserID</UserID>
<Token>Token</Token>
</AuthHeader>
</s:Header>
How do I add an "Inbound Policy" that would transform the request to XML and inject the custom header ?
Any ideas or suggestions would be greatly appreciated !!

For this requirement, please refer to the policy in my APIM.
<policies>
<inbound>
<base />
<json-to-xml apply="always" />
<set-body>#{
string inBody = context.Request.Body.As<string>();
string requestBody = inBody.Replace("<Document>","").Replace("</Document>","");
string header = "<s:Header><AuthHeader xmlns=\"http://abc.security.service\"><UserID>UserID</UserID><Token>Token</Token></AuthHeader></s:Header>";
return header + requestBody;
}</set-body>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Please pay attention to the escape character in header, we need to use \" instead of ".

Related

Azure API Management - named value at API scope

I am wondering whether it is possible to specify something like Named value but for each API separately?
So if I have, say foo-API and bar-API I can specify for each a named value-like variable, eg my-url. So now when I create a global policy
<policies>
<inbound>
<base />
<send-request mode="new">
<set-url>{{my-url}}</set-url>
<set-method>POST</set-method>
<set-body>something</set-body>
</send-request>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
but send-request will send request to the API specific URL (eg. different URL for DEV, TEST, PROD)
Not possible. Named values are a global collection, the only workaround is to name them to be descriptive enough, i.e. prefix with API id.

How to pass parameters in API request to back-end URL with Azure APIM?

I'm trying to create a request with parameters in Azure API Management.
I have the following API(returns all invoices):
www.apibackend.com/invoice
This API can also handle parameters like this(returns invoice with ID 1):
www.apibackend.com/invoice/1
In my APIM service I've got the following code:
<policies>
<inbound>
<base />
<set-backend-service base-url="www.apibackend.com/" />
<rewrite-uri template="/invoice" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
With the APIM URL(for example: www.apim.com/test/GetInvoices) I can make the following request to my backend:
www.apibackend.com/invoice
This will return all the invoices, but how do I only retrieve the invoice with ID 1? If i make the request "www.apim.com/test/GetInvoices/1" I will get an error.
Hope someone can help!
In APIM change your Operation template to GetInvoices/{id} then in policies you'll be able to do:
<rewrite-uri template="/invoice/{id}" />

Can Azure Api Management expose OpenAPI documentation?

We have some Azure Functions exposed through Api Management? Can Api Management expose a /swagger endpoint automatically, the same way the Swashbuckle package does for api's in Asp.Net.
Azure API management cannot automatically generate the swagger page. Azure API management only can provide you the API definition file. Then you can use other tools (such as Swagger UI) with the definition file to generate the page you need.
Besides, Azure API management has provided you the UI(https://youapimanagementname.portal.azure-api.net) to tell you how to use all the APIs.
You can expose your openapi documentation through the API itself.
The documentation of an API can be requested on
https://management.azure.com/subscriptions/[subscriptionid]/resourceGroups/[resourcegroupname]/Microsoft.ApiManagement/service/[servicename]/apis/[apiid]?export=true&format=openapi&api-version=2021-01-01-preview
Just create an additional operation (ex. openapi.yaml) on your API, call the url above through a custom policy and return the result. You can use the following policy
<policies>
<inbound>
<base />
<send-request mode="new" response-variable-name="result" timeout="300" ignore-error="false">
<set-url>#("https://management.azure.com/subscriptions/{{azure-subscriptionid}}/resourceGroups/{{azure-resourcegroup}}/providers/Microsoft.ApiManagement/service/" + context.Deployment.ServiceName + "/apis/" + context.Api.Id + "?export=true&format=openapi&api-version=2021-01-01-preview")</set-url>
<set-method>GET</set-method>
<authentication-managed-identity resource="https://management.azure.com/" />
</send-request>
<return-response>
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/yaml</value>
</set-header>
<set-body>#((string)(((IResponse)context.Variables["result"]).Body.As<JObject>()["value"]))</set-body>
</return-response>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
More info can be found on https://www.devprotocol.com/2021/07/20/expose-openapi-documentation-on-azure-api-management.html

Is it possible to use the subscription-key query string parameter with Azure API Management SOAP-passthrough?

We use API Management to expose several API's. One of the API's we expose is configured as a SOAP-passthrough API but we are facing some issues with it regarding authentication of APIM.
When we use the Ocp-Apim-Subscription-Key header for passing the query string it all works correct and the API is returning it's content correct.
When we use the subscription-key query string parameter the API is returning a 401 Unauthorized. I tested this behavior in Postman and changing the way of sending the subscription key is resulting in this behavior.
An implementation detail of this API is that it exposes an existing WSDL and routes this SOAPAction to an Azure Function via the policy. In the Application Insights of the function I can verify that the function is never invoked when I get a 401 but it is invoked when I get a successful call (using the header).
Is this normal behavior? Am I doing things wrong? Or is it a bug in APIM?
This might be an issue with the way we do routing for SOAP Passthrough. You will notice in the API setup that we add on a query parameter to identify the SoapAction that an operation will be matched to. It may be that your the api key query parameter is getting overwritten when adding the SoapAction parameter to the inbound request. I will investigate and let your know.
We currently use a workaround around this problem with the following policy. Instead of changing the backend-server url in the policy we send a request and set the response of that request as a response for this api. Below you can find our policy which is working with the subscription-key in the query string.
<policies>
<inbound>
<base />
<send-request mode="copy" response-variable-name="response" timeout="20" ignore-error="false">
<set-url>{{BackendServer_URL}}</set-url>
</send-request>
<!--return-response response-variable-name="reponse" /-->
<choose>
<!-- If StatusCode is not OK, return Unauthorized with the reason. -->
<when condition="#(((IResponse)context.Variables["response"]).StatusCode != 200)">
<return-response response-variable-name="reponse">
<set-status code="401" reason="Unauthorized" />
<set-body>#(((IResponse)context.Variables["response"]).Body.As<string>())</set-body>
</return-response>
</when>
<otherwise>
<return-response response-variable-name="reponse">
<set-status code="200" />
<set-header name="Content-Type" exists-action="override">
<value>text/xml; charset=utf-8</value>
</set-header>
<set-body>#(((IResponse)context.Variables["response"]).Body.As<string>())</set-body>
</return-response>
</otherwise>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

Azure APIM as pure proxy

I am trying to deal with an Backend API(REST) with no swagger documents to be accessed through Azure APIM.
I want all the calls directed to the Backend API with me not manually creating GET/PUT/POST for all the resources. My inbound policies for all operations is below
'
<policies>
<inbound>
<set-variable name="requestPath" value="#(context.Request.Url.Path)" />
<base/>
<set-backend-service base-url="https://*****/****/" />
<rewrite-uri template="#(context.Request.Url.Path)" copy-unmatched-params="true" />
</inbound>
<backend>
<base/>
</backend>
<outbound>
<base/>
</outbound>
</policies>
`
However when hit the APIM i was given
{
"statusCode": 404,
"message": "Resource not found"
}
Any help is appreciated Thanks
The easy way to do this is to create one operation for each HTTP method you support and use /* for the template. This will match any inbound path/query and forward it to the backend.

Resources