Scenario
In this fictitious scenario, I’m building a Pizza Delivery API. It’s composed of the following operations:
- GET Products is still in development, so I want to return a mocked response.
- GET Product returns the product information from Blob Storage.
- POST Order invokes a Logic Apps that creates the order in an async fashion.
- GET Order call an Azure Function that retrieves the specific order information.
- PUT Order is responsible to asynchronously update an order via Logic Apps.
- DELETE Order removes the order from within a Logic App.
In this blog, I’ll show you how to build this API, without writing a single line of code.
Walkthrough
Introduction
This section just demonstrates the basic principles to start creating your first Azure Function Proxy.
- Azure Function Proxies is still in preview. Therefore, you need to explicitly enable it within the Settings tab.
- Now, you can create a new proxy, by using the “+” sign. You need to specify a name, a route template, the allowed HTTP methods and a backend URI. Click Create to save your changes.
- When the proxy is created, you immediately get the proxy URL on which you can invoke the Azure Function Proxy. Via the Advanced editor link, you can define more options in a JSON format.
- The advanced editor is a JSON editor of the proxies.json file, that gives you more configuration options.
After this introduction, we can start the implementation of the Pizza Delivery API.
Mocking
This operation won’t have a backend service, because it’s still in development. We will mock a response, so the API can already be used for development purposes.
- Create a proxy GetProductsViaMocking. Provide the following details:
Route template: api/products
Allowed HTTP methods: GET
Backend URL: none, we will use mocking
- In the Advanced editor, specify the following responseOverrides. This sets the Content-Type to application/json and the response body to a fixed list of pizzas.
- If you test this GET operation, you’ll receive the mocked list of three pizzas!
Blob Storage
The GET Product operation will return a JSON file from Blob Storage in a dynamic fashion. Blob Storage is an easy and cheap way to return static or less frequently changing content.
- Create a blob container, named “pizza”. Set its access level to private, so it’s not publicly accessible by default. For every available pizza, add a JSON file that holds the product information.
- Create an Access Policy on container level. The policy provides read access, without any expiration. You can easily do this via the Azure Storage Explorer.
- Create a Shared Access Signature from this policy, via the Azure Storage Explorer. This gives you a URL (containing the SAS token), to access the blobs from the “pizza” container.
- To keep the SAS token better manageable, I prefer to add the SAS query string to the Application Settings of our Function App. Create an Application Setting BLOB_SAS_QUERYSTRING.
- Create a proxy GetProductViaBlobStorage. Provide the following details:
Route template: api/product/{productId}
Allowed HTTP methods: GET
Backend URL: https://pizzadeliverystorage.blob.core.windows.net/pizza/pizza-{productId}.json?%BLOB_SAS_QUERYSTRING%
Remark that the route template parameter ‘productId’ is reused in the Backend URL to get to correct JSON file.
Remark that the application settings can be retrieved via this %BLOB_SAS_QUERYSTRING% syntax.
- In the Advanced editor, specify the following responseOverrides. This sets the Content-Type to application/json
- If you test this GET operation, you get the product description of the corresponding product id.
Logic Apps
The asynchronous order operations will be tackled by a Logic App that puts the commands on a ServiceBus queue. Further downstream processing is not covered in this post.
- Create a Logic App as shown below. Remark that the Request trigger contains an {operation} parameter in the relative path. The request command is sent to an orderqueue, with the {operation} as a message property.
- Get the request URL from the Logic App. This also contains quite a long query string, that includes the API version and the SAS token. Similar to the previous step, insert the query string into an Application Setting named LOGICAPPS_SAS_QUERYSTRING.
- Create a proxy PostOrderViaLogicApps. Provide the following details:
Route template: api/order
Allowed HTTP methods: POST
Backend URL: https://prod-07.westeurope.logic.azure.com/workflows/370c425e220142cda2e0d0ec8c983e91/triggers/manual/paths/invoke/order/create?%LOGICAPPS_SAS_QUERYSTRING%
Remark that the create operation is passed via the Backend URL.
- If you test this POST operation, you’ll notice that the message is accepted.
- In the Logic Apps Run History, you should see that a new Logic App instance got fired.
- The message is now placed on the Service Bus queue. The operation has been set to create.
- Also create a proxy for the PUT and DELETE operation, in a similar way.
Azure Functions
- I’ve created an Azure Function that just returns a dummy order. The returned order ID is taken from the request.
- Deploy this Azure Function in a Function App and retrieve the URL. The URL contains a query string with the required access code. Add this query string to the Application Settings, named FUNCTIONS_CODE_QUERYSTRING.
- Create a proxy GetOrderViaAzureFunctions. Provide the following details:
Route template: api/order/{orderId}
Allowed HTTP methods: GET
Backend URL: https://pizzadeliveryservice.azurewebsites.net/api/orders/{orderId}?%FUNCTIONS_CODE_QUERYSTRING%
Remark that the route template parameter ‘orderId’ is reused in the Backend URL to pass it on to the Azure Function.
- If you test this GET operation, you’ll notice that a dummy order is returned, with the requested Id.
Feedback to the product team
After playing around with Azure Function Proxies, I have the following suggestions for the product team. They are listed in a prioritized order (most wanted feature requests first):
- The mocking experience is not ideal when working with JSON objects, as you need to constantly escape quote characters. It would be great if this could be made more user-friendly. As an alternative, you can reach out to blob storage, but this additional step decreases developer productivity.
- It would be nice if there is a way to remove all or some HTTP headers from the response. Each Azure service comes with its own set of HTTP response headers and I don’t always want them to be returned to the client application. This would be great from both a security and consistency perspective.
- Accessing parts of the request or response body would open up a lot of new opportunities. As an example, I’ve tried to put the message immediately on an Azure Storage Queue, without any code in between. However, this was not feasible, because I needed to wrap the original message content inside this XML template:
<QueueMessage>
<MessageText>{OriginalMessageContent]</MessageText>
</QueueMessage>
- Currently there is no way to perform different transformations, based on – for example – the backend response status code. This could become handy in certain scenarios.
Conclusion
Azure Function Proxies can be easily used to create an API that consists of multiple HTTP-based (micro)services. Practically every service can be accessed from within this light-weight application proxy, as long as the authentication is performed through the URL (e.g. SAS token, API key). This avoids that the client application needs to maintain a different URL per operation it wants to invoke. The service is very easy to use and requires no coding at all. A great addition to our integration toolbelt!
Toon
Subscribe to our RSS feed