Azure API Management - dynamic urls issue - azure

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>

Related

Azure API Management "rewrite-uri"

I am having difficulty adding text into my url path between my frontend and backend when using Azure Api Management.
I have a Azure functions api with a url like this:
e.g. https://pXXXXX-myapi.azurewebsites.net/api/pXXXXX/alm/{name}
The default api created by Azure API Management is this:
e.g. https://myapi.azure-api.net/pXXXXX/pXXXXX/alm/{name}
Ideally I'd like to Frontend to remove the redundant pXXXXX:
e.g. https://myapi.azure-api.net/pXXXXX/alm/{name}
If I remove it from the front end e.g. GET /pXXXXX/alm/{name} becomes GET /alm/{name}.
Then I receive a 500 error.
I assume this is because removing "/pXXXXX" removes it from the backend path as well.
So I have tried to use the rewrite-uri policy like so:
<rewrite-uri template="/pXXXXX/alm/{name}" copy-unmatched-params="false" />
I've tried multiple variations of this with no success.
Assuming
you've changed the frontend for your operation to "GET /alm/{name}"
and your backend function app service url is "https://pXXXXX-myapi.azurewebsites.net/api"
and your API Base URL is "https://myapi.azure-api.net/pXXXXX"
then rewrite-uri exactly like you pasted is correct. You want to add leading "pXXXXX" to the url.
I've reproduced exact same scenario on my side and it works.
500 error does not mean there is something wrong with the path. If you would wrongly configure your url you would get 404. Most probably there is an internal error inside your function app or other policies in the APIM. Just call this API with Ocp-Apim-Trace header set to true and subscription key that allows tracing and you will see what is wrong. Or you can paste trace here if you want so we can help.
Posting my own answer but thanks to those who tried to help.
I believe the issue came from an error from APIM itself.
I assume it was not setting up the policies correctly, because now it is automatically including set-backend-service in the inbound policy whereas it did not over the past 2 days when I have been repeatably re-creating my api.
Now my inbound policy looks like this:
<inbound>
<base />
<set-backend-service id="apim-generated-policy" backend-id="pXXXXX-myapi" />
<rewrite-uri template="/pXXXXX/alm/{name}" copy-unmatched-params="false" />
</inbound>
And my front end api looks as before:
/pXXXXX/alm/{name}

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.

In Azure API Management, is it possible to have a template parameter that allows slashes (e.g., a path)?

I'm using Azure Data Lake Storage to store a large amount of files. I'm setting up an Azure API Management gateway in front of it, which rewrites the URI and sets the backend service to the ADLS REST API (Gen2).
At this point I'm trying to configure the Path - Read pass-through. My operation in APIM is /data/{filesystem}/{path}?timeout={timeout}, which I would like to be able to call as follows:
(timeout is optional)
filesystem: MyFileSystem
path: Path/To/File.json
GET https://example.com/api/data/MyFileSystem/Path/To/File.json
However, when I navigate to this operation in the Azure Portal and use the Test feature, it reports the following error:
{ "message": "Unable to identify Api or Operation for this request. Responding to the caller with 404 Resource Not Found." }
I understand that APIM is likely looking for an operation matching /MyFileSystem/Path/To/File.json and cannot find one.
For what it's worth, my Path - List endpoint works as I'd expect, which is why I know it's specifically the {path} that's holding me up.
GET https://example.com/api/data/MyFileSystem?recursive=true&resource=filesystem
200 OK
I imagine I can change from a template parameter to a query parameter, but I'd prefer to avoid that route for now. So, is there a way to have a template parameter that allows slashes?
Yes. Last template parameter may have slashes. Use {*path}.
You are right Santi, slashes in template param will make APIM unable to find corresponding operation to handle requests.What's more, it is useless that you URL-encode the slashes as APIM will URL-encode your param again if it includes special characters which will mass the path.
I tested your scenario on Azure storage, if your use "\" to replace "/" it works well , you can have a try on it :

Azure Logic App Request Trigger authorization

I have a Logic App with an HTTP initial trigger that is all set up:
When I make the POST to the URL that is given to me (looks like https://___.azure.com/workflows/___/triggers/manual/paths/invoke?____), I get back:
{"error": {
"code":"AuthorizationFailed",
"message":"The authentication credentials are not valid."
}}
For this case, I need to accept anonymous calls.
Where in the Azure Portal do I setup the permissions for this?
The closest I've found is the "Access Control Configuration", and it is set like this:
Logic Apps does not allow anonymous calls, you are required to provide the SAS key, which is provided in Url generated on the request card.
Found the issue. My client-side code was appending a parameter to the URL without realizing the URL already had query parameters. As such, it was adding to the last parameter rather than adding a new parameter. With that fixed, the call works.
Yes, the URL that will be present at the callbacK URL while creating should work, Does your URL has SP, sv and sig query paramemters?

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

Resources