Rewrite target URL to header value - azure

Can API Management rewrite a backend URL to be the value of a request header? For example, if I have a request originating with header X-ProxyTarget: https://api.ipify.org/, and I send it to https://my-api.azure-api.net/proxy then can a policy (or combination of policies) on inbound (or backend) forward the request to https://api.ipify.org?

You can use the set-backend-service policy in the inbound section. This policy updates the backend URL as provided and read the input header value to set the url.
Sample Code:
<set-backend-service base-url="#(context.Request.Headers.GetValueOrDefault("X-ProxyTarget","http://my-api.net"))" />
References : https://learn.microsoft.com/en-us/azure/api-management/api-management-transformation-policies#SetBackendService

Related

Azure API Management - dynamic urls issue

I have a frontend url say - 'https:\test.helloweb.com\account' which is defined a post request /person and I want to direct any request that comes on that url to a backend url like so
'https:\secure.hiddenapi\vi\api\person'.
The above scenario is easy and works now the place where I'm stuck is if there is a request for
Say -
/person/<id>/membership
/person/<id>/membership/<memid>
/person/<id>/accountdetails/
these requests needs to be directed to
https:\\secure.hiddenapi\vi\api\person\<id>\membership
https:\\secure.hiddenapi\vi\api\person\<id>\membership\<memid>
https:\\secure.hiddenapi\vi\api\person\<id>\accountdetails.
I tried defining the operation as /person/* then if i make a request to /person/<id>/membership then the backend url called is https:\\secure.hiddenapi\vi\api\person\membership without the id.
Seems like a simple issue but cannot make any progress!
Here is how APIM maps URLs. Consider:
An API with:
API URL suffix set to "myapi"
Web service URL set to "https://contoso.com/api"
An operation with:
URL template: "/myoperation"
When APIM receives a request it will split it into two parts:
https://service.azure-api.net/myapi/myoperation
^ ^
API base URL operation path
It will then replace API base URL with "Web service URL" specified for matched API and this will become request to backend:
https://contoso.com/api/myoperation
In your case, given that you end up with "person/person" it is likely you have "person" in both Web service URL and operation URL template. So you have two options.
First option is to configure Web service URL as "https://secure.hiddenapi/vi/api" and let all your operation templates start with "/person".
Another way is to set service URL as "https://secure.hiddenapi/vi/api/person" and do not include "/person" into your operation URL templates. It's perfectly fine if operation URL template starts with a variable like "{id}/membership/{memid}".
It's a good practice to split your whole backend API into different APIs in APIM for control and management. So personally I'd prefer first option, and if later there would be a need to make request to backend with prefix different than "/person" I'd create another API.
Try using rewrite URL policy to route to different backend URL for specific operation as follows:
<inbound>
<base />
<rewrite-uri template="/accountdetails/" />
</inbound>

Why does Power Query call Azure API Management backend URL?

I have an Azure App Service hosting an OData endpoint that is behind an Azure API Management (APIM) instance. To prevent calling the App Service directly it is protected by a certificate that only the APIM has.
When I call the APIM URL through Chrome or Postman, it behaves as expected. Just one request with no redirects or funny business, and it returns the OData root.
Here is a Fiddler log of a request to the APIM using Postman
However, when using the same URL as an OData source in Power Query using OData.Feed(), it returns a 301 which forwards to the backend URL, which obviously fails because that URL is protected by a certificate. Here is a Fiddler log of a request to the APIM using Power Query in Excel
I've configured the subscription key to be passed in the headers, but I've also tried it as a query param and it doesn't work in Power Query either way. I've also tried using an OData entity endpoint directly (to avoid the $metadata call) with no luck.
The user agent Power Query uses is Microsoft.Data.Mashup, but I haven't found any documentation about its compatibility with APIM, but that shouldn't matter, right?
In typical fashion after working on this for two days, I discovered the answer right after posting on StackOverflow. I'll leave this question up in case anyone has the same issue.
The problem was that the Power Query connector automatically follows #odata.context links for metadata, and #odata.nextLink links for paging. These links still had the app service site as the host instead of the APIM host.
So a quick edit of the outbound rules in APIM was able to fix the issue
<outbound>
<base />
<set-variable name="backendBaseUrl" value="#(context.Request.OriginalUrl.Scheme + "://" + context.Request.OriginalUrl.Host.ToString() + context.Api.Path)" />
<find-and-replace from="#("http://" + context.Request.Url.Host.ToString())" to="#((string)context.Variables["backendBaseUrl"])" />
<find-and-replace from="#("https://" + context.Request.Url.Host.ToString())" to="#((string)context.Variables["backendBaseUrl"])" />
</outbound>
Here I have to rules to replace http and https URLs just in case some configuration changes.

How do I enable CORS on Azure Storage Blob

I am trying to customize the UI page on Azure B2C using an Azure storage blob using this article. It needs to be CORS enabled. I have tested it using test-cors.org and I know it is not but I do not know how to set it
Ther article uses https://wingtiptoysb2c.blob.core.windows.net/b2c/wingtip/selfasserted.html which I test and returns a 200 but mine does not
https://bookssorted.blob.core.windows.net/b2c/selfasserted.html
This article talks about using this PUT https://myaccount.blob.core.windows.net/?restype=service&comp=properties HTTP/1.1 but how do I run this?
EDIT: I am using Azure Storage Explorer and I have these rules set on the blob but it is still not returning a http 200 from test-cors.org
EDIT2: this is the url that makes the request to the authentication policy which loads the page that makes the request to load the blob
https://login.microsoftonline.com/bookssorted.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_bookssortedAuthenticationPolicy&client_Id=35f308cd-8914-4035-9f62-cec7600c1727&nonce=defaultNonce&redirect_uri=https%3A%2F%2Flocalhost%2Fbookssorted%2Fsecure%2Fsuccess&scope=openid&response_type=id_token&prompt=login
EDIT3: headers as requested
In order for a cross-origin request to succeed, the request must match the CORS configuration. This includes the request origin, request headers & exposed (response) headers. Any mismatch there would result in request to fail.
If the origin is known, then that URL must be specified (including protocol & port number if applicable) in the CORS rule. If the origin is not known and you can specify * as the origin and all URLs will be able to make such requests.
Same thing goes for request headers and exposed headers. Since different requests to Azure Storage make use of different request headers and return different response headers, it is advisable to set the value for these as * in the CORS rule. This will ensure that all request/response headers are accepted.

How to send Query Parameter to Logic App from API Management

I am receiving a GET request in API management (https://devapi.testcustomer.com.au//bankv2?bsbNumber=123-456) and transforming it to POST call to Logic App. How can I pass the bsbNumber query parameter from the incoming request to Logic App?
I am setting the logic app Url inside API Policy:
<set-backend-service base-url="https://prod-05.*******.logic.azure.com:443/workflows/******b187aef1f5/triggers/request/run" />
<set-method>POST</set-method>
<rewrite-uri template="?api-version=2016-06-01&sp=%2Ftriggers%2Frequest%2Frun&sv=1.0&sig=*****tdiDL8" />
You will have to use the expression context.Request.Url.Query.GetValueOrDefault("bsbNumber")
to get the value of bsbNumber from querystring. You can use it to create a parameter in the redirect URI.
List of all possible expressions in Azure API managment.
https://msdn.microsoft.com/en-us/library/azure/dn910913.aspx

any reason to use an outbound policy in apim?

Is there any reason to use an outbound policy in APIM? I tried a test where I used the same policy expression for inbound as well as outbound. The same expression worked without error and returned the same info for both. I don't see any need to configure an outbound policy if an inbound expression already captures all of the information. Have you also found the outbound section to be redundant and simply excluded the outbound section? Or have you found any reason to use the outbound section in addition to the inbound section?
Outbound policies can be used to manipulate/inspect a response body or headers returned from a backend API.
Examples of things you might do in an outbound policy:
Set the cache duration based on the Cache-Control header returned from the API
Remove headers created by the API framework like X-Powered-By and X-Aspnet-Version
Calculate an etag value using a checksum of the body
Create a signature header to prevent tampering with a response body
Update the returned response body with cached fragments
Log the returned response to a diagnostic system or audit trail

Resources