When working with lots of Azure Functions apps or in microservices architectures with a moderate workload, it’s quite common to use (or at least evaluate using) a not so well-known feature of Azure Functions called proxies.
What are Azure Functions proxies?
With proxies, you can specify endpoints on your function app that are implemented by another resource. You can use these proxies to break a large API into multiple function apps (as in a microservice architecture), while still presenting a single API surface for clients.
Azure Function Proxy can be seen as a unified API layer on top of Azure functions hosted inside the Application Service container. It exposes a set of additional HTTP endpoints in front of functions based apps.
A proxy for an Azure Function app can be created by going to Proxies and then filling the Route template (new endpoint with parameters), the supported methods and the Backend url (url where the proxy will redirect the calls). This endpoint could be a function in the same app or in another function app, or it could be any other API you have. Proxy calls are billed the same way as Azure Functions (a proxy is essentially another pre-warmed function).
Here for example I have a function app that exposes a ProcessOrder function. I have created a proxy that expoxes a api/ProcessOrder endpoint and taking an orderId parameter as input. Then the requests are routed to the backend url:
In the case where the backend url is in the same function app where you define the proxy, you can use localhost
to reference a function inside the same function app directly, avoiding a roundtrip proxy request.
You can also reference application settings defined for the function app by surrounding the setting name with percent signs (%). For example, a back-end URL of https://%ORDER_PROCESSING_HOST%/api/ProcessOrder would have “%ORDER_PROCESSING_HOST%” replaced with the value of the ORDER_PROCESSING_HOST setting.
You can also configure proxies by code (useful to automate deployments) by creating a proxies.json file located in the root of a function app directory (your Azure Function project). An example of configuration via JSON file is the following:
{ "$schema": "http://json.schemastore.org/proxies", "proxies": { "proxy1": { "matchCondition": { "methods": [ "GET" ], "route": "/api/{EndpointName}" }, "backendUri": "https://.azurewebsites.net/api/" } } }
By using proxies, you can have different Azure Function apps all responding to a common API layer (url and so on). You can also specify request and response override for each method.
What changes now?
Azure API Management is Microsoft’s solution to securely create and manage modern APIs at scale. It also provides advanced tools for building and maintaining APIs such as OpenAPI integration, rate limiting and exhaustive policy support.
Azure Functions Proxies are a very limited subset of these capabilities that will no longer be invested in to avoid duplication of functionality. Azure Functions Proxies will continue to remain in maintenance mode until 30 September 2025 after which they will no longer be supported.
If you’re using proxies in some of your project (like me) you should transition to Azure API Management as soon as possible to be on the recommended and long term supported path.
Transitioning is quite simple. You need to create an instance of the Azure API Management service and from here select APIs. In the Add a new API list, select Function App:
The Create from Function App page opens and from here you can select your Azure Function app to import and you can specify the parameters of your new “proxy” endpoint in API Management:
When imported, you will have a new API with the function endpoints exposed:
From here you can create Inbound and Outbound policies and more.
You can also add other Function apps to the same API in Azure API Management by clicking on your API definition and selecting Import:
This is recommended if you want to have a common API namespace (endpoints) for a set of Azure Function apps (microservices architecture).
When imported, you can directly test your Azure Function app endpoints in Azure API Management directly from the portal. In this sample, I’ve imported an Azure Function app that I’m using to generate barcodes. The Function app by default responds to the following endpoint:
https://sdqrcodegenerator.azurewebsites.net/api/QRGenerator?code=FUNCTIONKEY&url=http://www.demiliani.com
The new endpoint when imported in Azure API Management will be:
https://sdazureapimgt.azure-api.net/SDQRCodeGenerator/QRGenerator?url=http://www.demiliani.com
When testing via the API Management portal, you can specify the query parameters (if GET) or header parameters (for POST) and you can see the response of the API endpoint called:
Please remember that the import of an Azure Function App in Azure API Management automatically generates:
- Host key inside the Function App with the name apim-{your Azure API Management service instance name},
- Named value inside the Azure API Management instance with the name {your Azure Function App instance name}-key, which contains the created host key.
Removing or changing either the Azure Function App host key value or the Azure API Management named value will break the communication between the services (the values are not automatically in synch). If you need to rotate the host key, make sure the named value in Azure API Management is also modified.
To call the Azure API Management endpoint for your function app from external applications, remember that you need to pass the “Ocp-Apim-Subscription-Key” tag in request header with the product subscription key associated with this API. Here is a quick C# example on how to do that:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(ENDPOINT_URL); request.Headers.Add("Authorization", BearerToken); request.Headers.Add("Ocp-Apim-Subscription-Key", "YOUR_OcpApimSubscriptionKey");
To retrieve the key, select the Subscriptions blade in your Azure API Management instance and show the following key:
Now you’re ready to rumble with your newly created Azure API Management-based proxies for your Azure Function apps and you can apply policies to them (IP filtering, rate limits and more). For example, to allow access to only some incoming client IP addresses, create an Inbound policy with the ip-filter policy filters:
You can then specify the allowed or blocked IP addresses or ranges:
and this creates an XML policy definition like the following:
address
You’re now ready to start exploring the microservices world and please remember the deadline if you’re using proxies or if you plan to use them.