Using Azure API Management to replace some App Service APIs with Azure Functions

Andrew Leader
7 min readNov 19, 2019

Do you have a traditional Azure App Service powering your website and API, but want to modernize some of the APIs with Azure Functions? But you don’t want to change your domain or URLs?

Azure API Management is the perfect fit! You can keep your same domain and URLs, but selectively choose some paths to route to the Function rather than the App Service!

I recently used Azure API Management to modernize some of Power Planner’s back end, a homework planner app that I work on in my free time. I have a lot of APIs (and the website) powered by an ASP.NET App Service, but I wanted to move the most heavily used APIs to Azure Functions, so I could take advantage of the serverless scaling.

For example, I wanted to move the sync API to Azure Functions: https://powerplanner.net/api/sync. But I also have other APIs like https://powerplanner.net/api/login, /api/createaccount, etc… And, I didn’t want to update all of my clients to point to a new URL for some of the APIs (I have client apps for Android, iOS, and Windows). I wanted to be able to control, from the server-side, what endpoint each URL request routes to. And I wanted it to be affordable too.

So, how do you set it up?

Step 1: Create your Azure Functions

First create your functions. I created a “PowerPlannerData” function app, with a sync function. Make sure your function either uses Function authentication or Anonymous authentication, as those are the only two options API Management supports (you should pick Function authentication).

This function has its own URL, https://powerplannerdata.azurewebsites.net/api/sync… So while I could update my app clients to call that URL when syncing, I’d rather avoid a client-side change (plus what if one day I want to move off of Functions for the next better tech?).

Step 2: Create an Azure API Management instance

Here’s the key… Use the consumption plan. Otherwise, it’s way too expensive for a hobby app. Consumption plan works the same as functions, you only get billed for what you use.

Step 3: Add your App Service to the API

Then, in the APIs menu, you need to add two APIs… An “API app” (your App Service), and a Function App (your function).

Adding the API app is pretty straightforward… Leave the API URL suffix blank, so that it forwards ALL requests to ANY path to your App Service

Leave API URL suffix blank

After it’s created, go to the settings, select URL scheme to be Both (assuming your app service handles forwarding to HTTPS, since you probably want your website to work when people just type in the domain name). Also make sure to add a product (APIs won’t be public till you’ve added a product). And uncheck Subscription required, as you want your website to work without an API key in the header.

Save the changes, and then try out your API! Go to https://<yourapi>.azure-api.net, and watch it automatically act as if it’s your normal app service! Everything works!

Step 4: Add the Azure Function to the API

Now to selectively pick some paths to forward to the Azure Function rather than the App Service. Go back and add another API, this time the Function App.

Select Function App this time

This time, set the API URL suffix to the path you want to override… In my case, api/sync

Then, just like before, after creating the API, go to the settings, add a product and uncheck subscription required.

Now try hitting https://<yourapi>.azure-api.net/api/sync, and notice it invokes your function! You can override as many paths as you want using this technique.

Step 5: Switching your custom domain to API Management

After you’ve tested everything out and confirmed it’s all working, the final step is to switch your custom domain DNS settings to point to your azure-api.net domain rather than your App Service!

There’s a few gotchas to be aware of…

The consumption plan doesn’t give you a stable IP Address. That means if you want your root domain (like powerplanner.net rather than api.powerplanner.net) to point to the API Management, you have to use some special features depending on your DNS provider. Root domains are required to have A records that point to a specific IP address. However, you don’t have an IP address to use!

Some DNS providers, like Namecheap, support an “ALIAS record” option, where you CAN specify a domain for the root (similar to CNAMEs). The DNS provider then dynamically resolves the IP address of the domain and returns it as an A record. Azure DNS unfortunately doesn’t support this, so if you’re using Azure DNS (which I was), you have to switch off of it.

Another gotcha is that you need a CNAME pointing to API Management… API Management verifies this when assigning the custom domain… but you’re not allowed to use CNAMEs for the root domain! However, Namecheap to the rescue once again… Namecheap allows you to set a CNAME for the root. And this seemingly worked perfectly fine, although I later switched to the ALIAS record option after I got it configured, just to be safe.

The third gotcha: Your custom domain on the App Service will cause infinite loop requests. When API Management forwards calls to your App Service, it forwards based on the configured domain of your App Service. Therefore, a GET request for powerplanner.net/platforms comes into API Management, determines it should route to the App Service, and then calls the App Service using the App Service’s domain, which is also powerplanner.net/platforms… which simply just calls back to API Management! So you need to first remove the custom domain from your App Service.

The fourth gotcha… If you’re using Azure’s SSL certificates, you can’t directly use the certificate in API Management. You have to first export it as a PFX, and then re-upload it to Key Vault as a certificate. Azure’s SSL certificates store the certs in secrets for some reason, which API Management doesn’t allow reading from (it only lets you read from certificates).

How do you switch the domain without any downtime?

It’s a bit complicated, but here’s what you do…

  1. If using Azure App Service Certificates for your SSL certificate, first export the certificate as a PFX and re-upload it to Key Vault as a certificate
  2. If using Azure DNS and you want to use your root domain, switch to a different DNS provider, like Namecheap (you’ll have to switch all your records over, type them in fast to ensure no downtime! Just transfer your existing records as is first).
  3. Create a new App Service without your custom domain: To avoid the gotcha with the requests re-routing to themselves, you have to create a new App Service without a custom domain and deploy your code to that App Service
  4. Point your API Management to that new App Service: Delete the old App Service API and add that new one. Now instead of routing requests to https://powerplanner.net (which would route back to the API management itself), it’ll route to https://powerplannerapp.azurewebsites.net… You probably could also remove the custom domain from the existing App Service, but that seems likely to cause downtime.
  5. Prep the custom domain in API Management: In the Azure portal for the API Management instance, select Custom domains, add a new one, and type in everything (your custom domain, select your SSL cert)… but don’t click add yet (you can try, it’ll just fail because you don’t have the CNAME record yet)
  6. Add the CNAME: In your DNS provider, add the CNAME pointing to the <yourapi>.azure-api.net domain (this will require removing your current record, so move fast from here on out…)
  7. Add the custom domain in API Management: Now go back to your prepped custom domain in the portal and click add! It should correctly validate that the CNAME is pointing to the API Management domain and it’ll add!
  8. Switch to ALIAS record: If desired and if using the root domain, swap out your CNAME record for an ALIAS record, since CNAMEs technically aren’t supposed to be used for the root @ record (but you needed the CNAME for API Management to initially validate and accept adding the custom domain).
  9. After a couple days, delete old app service: DNS records take a while to propagate. I still have requests hitting my old app service a day later. Monitor it and eventually delete the app service after the traffic stops.

Quite complicated! But once you’ve got it set up, it’s worth it! Now, if I decide I want to host some of my websites pages out of Azure Storage rather than an ASP.NET app, I can dynamically select which paths map to storage! It’s super useful!

--

--

Andrew Leader

Program manager on Windows Dev Platform, dev of Power Planner, rock climbing/hiking/skiing enthusiast, mountain rescue