wiki

Codit Wiki

Loading information... Please wait.

Codit Blog

Posted on Wednesday, October 4, 2017 1:52 PM

Toon Vanhoutte by Toon Vanhoutte

By creating a uniform API on top of several heterogenous service operations, we also simplify the security model for the API consumer.

After the configuration we've done in part 1, we've hidden the complexity of maintaining 4 SAS tokens and 1 function code client-side. Be aware that, at the moment, the Azure Function Proxy is not secured by default. In some cases, this might be the desired behaviour, in other scenarios we would like to restrict access to the API. Let's have a look how we can achieve the latter!

Enforce Authentication

You can leverage the default App Service authentication feature, that forces clients to get authenticated against one of these providers: Azure Active Directory, Facebook, Google, Twitter & Microsoft. This can be done without any code changes. This only covers authentication. When authorization is required, some minimal code changes are needed.

Suggestions for product team

  • Common security measures like IP restrictions and configurable rate limits to protect against DoS attacks would be great. There is already a feature request on UserVoice.

  • Leveraging the standard Azure Function keys or host keys would be also a simple way to authorize the API endpoint. You can easily setup rotating keys to improve security. Apparently this is on the radar, but no ETA defined yet!

Cheers,
Toon

Categories: Azure
Tags: Functions
written by: Toon Vanhoutte

Posted on Tuesday, October 3, 2017 9:28 AM

Stijn Moreels by Stijn Moreels

In this post, we will look at how F#'s feature Active Patterns can help build a clear, declarative solution for the Validation of Domain Models. By using a Partial Pattern for each Business Rule, we can clearly see how the input is restricted to verify each rule.

Introduction

The reason I wrote this post was to learn more about F# Active Patterns, and how I can use this for certain, specific problems. They say this feature is a real “killer” feature of the F# environment, so I found it a good exercise to think about how I can use this in my daily practice.

Scott Wlaschin has an amazing blog post series where he writes about this topic. He shows how we regularly miss the true definition of the domain and how we can fix this with the simplicity of F#.

My blog post builds upon that idea and looks how we can validate our models in the same simplicity.

Domain Modeling

When thinking about the modeling of the domain, F# has a very nice way to express this. Throughout this post, I will be using F# for my modeling and for the validation of my model. Sometimes I will show your what the alternative would look like in an Object-Oriented Language like C#.

Book

Ok, let’s define our model. We want to define a “Book” in our domain. A book in our domain has several items which defines “a book”; but for the sake of this exercise we’ll keep it very short:

Just like Scott Wlaschin has asked the question, I'll ask it again: “What’s wrong with this design?”.

Several things, as a Security Expert you could say that we’re could have a problem if someone enters negative pages, or special chars for the ISBN or the Author.
As a Domain Expert, you could say that this model doesn’t actually represent the domain.

PositiveInt

Let’s start with a simple one: we can’t have negative pages; so, let’s define a new type for this. Note that we have cleared it “private” so we can’t call this new type directly via its Value Constructor. Because we have made it private; we need another function that will create this type for us. When we enter a negative number, we can’t create a type. That’s sounds like an Option to me:

FYI: At this point, Scott's talk stops because the talk is about the domain itself and not to specify how we can refactor the validation of the models.

Now we can start with the refactoring to Active Patterns. Because this is a simple type, I think you can’t see the immediate benefit of this approach; so, hang on. We use the Partial Pattern approach for these Business Rules because we can’t wrap all possible values in a single pattern.

The Partial Pattern approach needs a return type of unit option. We can use the Some branch to return the pattern itself and the None branch can be used to specify that the input doesn’t match this pattern.

One can argue about the over-engineering of this approach; but personally, I find this a way more simplistic approach than the inlined Guard Clauses in the Match Expression.

Our book looks now like this:

String50

Next up, is the author’s name. It reasonable to think that the length of the name will be no longer than 50 chars.

We can specify all these rules in our model the same way as we did with the pages:

Notice that we now have two branches that cover our type. By extracting the rules into Partial Patterns, we have made it clear, in our Constructor Function, that we need a string that isn’t “null” or empty and is a maximum of 50 characters long.

Now, how would we specify this in C#? Because we do not have an option type by default, only a less stronger Nullable<T> type; we normally use exceptions.

Note that we can reuse the pre-conditions for the empty string and the length across our application in the F# version, while we must redefine them for every class in C# (except off course we extract this functionality in some “utility” classes.

Now, our book type looks like this:

ISBN13

The last type is the most interesting and the reason why I would use Active Patterns for my Domain Model Validation.

If we have some more complex type for example an ISBN13 number; how would we model that? First of all, let’s specify some requirements:

  • Number must have length of 13
  • Last number is checksum

The checksum is calculated by evaluating the following steps:

  1. Take the 12 first chars
  2. Multiply the even numbers in the sequence with 3
  3. Take the sum of all the results
  4. Modulo 10 the result
  5. Substract 10 if the outcome isn’t zero
  6. Final result must be the same as 13th number

I came up with this:

What I like about this, is the declarativity of the checksum calculation and the fact that you can see immediately what rules we have in our ISBN validation.

Note that I changed the Active Pattern for the length of the string by passing in a function; this way I can reuse it for my String50 type and for this one AND can you see more clearly what exactly we're trying to validate with the string's length (greater than, equal to, ...).

Now, I wanted to check this with C#. To achieve the same level of simplicity; we would extract each rule in it’s own method:

If we extract each rule in a method, I think we get that same simplicity. But we should send some arguments with the rules not just for reusability in other models but for readability as well.

Take for example the Regular Expression rule. It’s much simpler to just send the pattern with the rule than to come up with some name for the method (or Active Pattern) that would satisfy what you’re trying to verify.

Note that the C# version isn’t done yet and must be refactored since there’s a lot going on which can’t be comprehend as quickly as the F# version (but that's just my opinion).

Before you say anything about LINQ, I explicitly used and imperative approach because otherwise we would use functional programming again and when I compare functional with imperative I always try to be functional and imperative in the extreme so I can quickly see what's the actual difference is.

 Testing

Of course, to be complete let’s write some properties for our newly created types. I found not every type to be that obvious to write properties for so it might be a good exercise for you as well.

PositiveInt Properties

First, let us look at the positive integer type. This was the simplest type to model and is also the simplest type to test. I came up with these two properties for the two branches:

String50 Properties

The next type must have a length of 50 chars to be a valid type. Following properties came to mind:

ISBN13 Properties

Now, the last type is probably the most interesting. We must generate valid ISBN numbers to check if the checksum acts properly. I came up with a Test Oracle as another way to express the checksum so I’ll could filter with this expression to generate valid ISBN13 numbers:

I love the way FsCheck allows me to write such properties with such little effort. Now I have a way to generate random, valid ISBN13 numbers. Notice that I didn't check the other Active Pattern branch, perhaps this is a good exercise for you? All other cases should result in None.

Small side note: the assertion is now valid (accessible) because I wrote the types and properties in the same file. When this isn't the case, we could test for any type (with wildcards) wrapped inside a Some case, instead of actually creating an ISBN13 or any other type. That way, we could change the values for that type without changing our test. For the sake of this exercise, I thought it was clearer to assert the type this way.

Love to hear your opinion!

Conclusion

In this post, we looked at how F#'s feature Active Patterns can help build a clear, declarative solution for the Validation of Domain Models. By using a Partial Pattern for each Business Rule, we can clearly see how the input is restricted to verify each rule.

In an object-oriented approach, you would normally create a class to wrap the domain model and specify the business rules inside the constructor while in functional programming, this can be done by privatizing the Value Constructor and create a new Constructor Function which uses Active Patterns to specify each business rule.

Thanks for reading!

Categories: Technology
Tags: F#
written by: Stijn Moreels

Posted on Monday, October 2, 2017 10:33 AM

Toon Vanhoutte by Toon Vanhoutte

Connecting cloud services to on premises API's can be quite challenging. Depending on your setup, there are multiple options available. The most enterprise grade options reside on the network level: ExpressRoute and Site-to-Site VPN. Another option is leveraging Azure App Service Hybrid Connections, which gives you a very simple way to connect to on premise resources on the TCP level, in a firewall-friendly and high available manner. This blog will demonstrate how you can consume an on premises API via Azure Function Proxies, without any coding at all.

You can find the documentation of Azure App Service Hybrid Connections over here.

Instructions

Following these instructions to setup hybrid connectivity through hybrid connections:

  • In order to take advantage of hybrid connections, you must ensure that you create the Azure Function Proxy within an Azure App Service Hosting Plan.

 

  • Navigate to Platform features and click on Networking

 

Consumption plans do not support networking features, as they are instantiated at runtime.

  • Click on Configure your hybrid connection endpoints

 

  • Download the Hybrid Connection Manager

  • Start the installation with accepting the License Agreement.

  • The installation doesn't take long.

  • Click Finish to complete the installation.

  • Open the Hybrid Connection Manager UI desktop app.

  • At this moment, you should not see any hybrid connection. Ignore the 'mylaptop' connection in the screen capture below, as this is still a legacy BizTalk hybrid connection.

  • Back in the Azure Function Networking blade, click Add hybrid connection.

  • Choose Create new hybrid connection.

  • Give the connection a name, provide the endpoint host name and port. As Hybrid Connections leverages ServiceBus relay technology underneath, you need to provide a ServiceBus namespace.

  • Choose in the local Hybrid Connection Manager to Configure another Hybrid Connection.

  • Select the previously created hybrid connection and click Save.

  • If all goes well, you should see the Connected status for the hybrid connection.

  • The Azure Portal should also display a Connected status.

  • You can configure now the Azure Function proxy with an external / public URL to point to the local backend URL, which is now available through the Hybrid Connection Manager.

Now you can access your local API from the external world! Be aware that there is currently no security measure applicable. This will be covered in the next part of this blog post series.

High Availability

In case you need high availability, you can install another Hybrid Connection Manager that connects to the same hybrid connection. The documentation states the following:

Each HCM can support multiple hybrid connections. Also, any given hybrid connection can be supported by multiple HCMs. The default behaviour is to round robin traffic across the configured HCMs for any given endpoint. If you want high availability on your hybrid connections from your network, simply instantiate multiple HCMs on separate machines.

Enjoy this easy hybrid connectivity!
Toon

 

 

Categories: Azure
Tags: Functions
written by: Toon Vanhoutte

Posted on Thursday, September 28, 2017 12:46 PM

Stijn Moreels by Stijn Moreels

“Property-Based Testing”, ever heard of it? It’s a very popular topic in the functional community. The opposite of this approach is the well-known “Example-Based Testing”. People think in examples and that’s why it’s so popular; also in the non-functional community. This is/was the way we write/wrote tests.
“Given a static, constant example; the output should be this”
But is that the best we can do?

Introduction

Property-Based Testing is about generalizing the input so we can make statements about the output; without specifying exactly what the input or output should be, only should look like.

I’m not going to give you the full-introduction because there are already so much good resources about this topic, (also in different languages).

But what I will do, is give you an introduction to FsCheck in a C# environment. FsCheck is written in F# but has a C#-friendly API. I’m going to use the FsCheck.Xunit package for this blog post.

FsCheck

For a full-introduction of FsCheck itself, I highly recommend the documentation of FsCheck; with a good explanation about the framework. Although they give a good idea of how the framework is built, I find it hard to find examples of how it can be used concretely; especially if you’re using the xUnit variant.

Several blog posts are using F# to make properties with FsCheck, but with C# the posts are rather rare…

Fact to Property

Let’s start from the xUnit example they present on their documentation:

If you know xUnit, you know that ‘Fact’ is the way xUnit marks methods as test-methods and the static class ‘Assert’ is used to assert on the result.

Now, I’ll give you the same example but written with some FsCheck properties:

What are the differences?

  • The ‘Fact’ attribute is changed to ‘Property’ attribute
  • Return type is ‘Property’ instead of ‘void
  • Assert’ class isn’t used, but the condition is returned and transformed by the ‘ToProperty()’ call to a ‘Property
  • The inputs of the method under test aren’t hard-coded anymore

This last difference is probably the most important one.
I highly recommend you read the resources if you haven’t heard about PDT because I won’t list all the benefits of Property-Based Testing. I hope that you see that by using this approach, I can’t maliciously fake the actual implementation anymore, while in the first example I could have done this.

We’ve added two parameters to the test method that FsCheck will fill-in for us with some random values. This will contain negative, zero and positive values all in the range of an Int32 data type. All valid integers so to say. FsCheck will, by default, run 100 tests with random values for the inputs of the test.

FsCheck has several extension methods on boolean values, like the one above. Let’s look at some more.

Conditional & Lazy Properties

Sometimes, we want to restrict the input to make sure you’re always end up with the same output. A simple example is the mathematical division. You can’t divide by zero, so to have the same result we must make sure that the given input isn’t below zero.

What’s different?

  • We added the ‘When()’ call to specify that we can’t divide by zero (this makes sure we don’t have to call ‘ToProperty()’ again)
  • We extracted the method, which we wanted to test, in its own delegate. Note that FsCheck has extension methods on any delegate that returns a boolean.

That is a good example of the Conditional Property; but why do we need to extract the call to ‘Divide’? Because otherwise FsCheck will evaluate this immediately (even with ‘y’ being zero) which would result in a ‘DivideByZeroException’ and FsCheck will treat any exception being thrown as a test failure. That’s why.

By extracting this, we’re telling FsCheck that we’re only interested in the results IF the condition holds. In our case: ‘y’ must be zero.
That’s convenient!

With this simple example, we’ve shown how we express conditions in our properties to make sure we’re always in a given set of inputs, and shown how we can create Lazy Properties which are useful to only evaluate the test if the condition we’ve set holds. This also can be useful if the actual test takes some time and we don’t want to lose time while evaluating a test which result isn’t of interest for us.

Exception Properties

In functional programming, I’ll try not to use any exceptions in my code; but in imperative languages this is the way to express something went wrong. We also write tests that trigger those exceptions that we throw by giving invalid inputs.

The xUnit package also has some methods on the Assert class called “Throws”, “ThrowsAny”, ... How can we express this in FsCheck?

The documentation says that this isn’t actually supported in C# (you can see it at the lower-case method); but writing it this way works.

Observed Properties

The best possible alternative for this feature, is the ‘usermessage’ you can send with the ‘Assert’ class in the xUnit package. We send a string with the assert so we can later see which assertion has failed.

FsCheck takes this a step further.

Trival Properties

FsCheck has a way to count the cases for which a condition is met. In our previous example, can we count how many generated values are negative values?

In our test output, we can see that the positive and negative values are almost split in half:

Ok, passed 100 tests (47% trivial).

Try to run them again and see how this test output change.

Classified Properties

Sometimes, we want more than one condition to check about our input and maybe add some custom message for each category of input. According to me this is the closest thing to the ‘Assert’’s ‘usermessage’.

FsCheck has a way to express this by classifying properties.

In our output, we’re now seeing:

Ok, passed 100 tests.
63% Smaller than '1000'.
37% Smaller than '1000', Bigger than '10'.

See, how the categories can also be combined and are shown to the user in a friendly way.

Collected Properties

We’ve seen some examples how we can express some categories for our test inputs by specifying conditions on them and giving them a name. But sometimes we’re just interested in the actual input value itself and how it changes during the test run.

This will result in this test output:

Ok, passed 100 tests.
8% "Values together: 0".
5% "Values together: 8".
5% "Values together: 1".
4% "Values together: 3".
4% "Values together: -12".
3% "Values together: 38".
3% "Values together: 2".
3% "Values together: -4".
3% "Values together: -14".
3% "Values together: -1".
2% "Values together: 9".
2% "Values together: 7".
2% "Values together: 5".
2% "Values together: 32".
2% "Values together: 21".
...

This way, we can clearly see how the test inputs changes over time.

Combined Observation Properties

As a final observation property, we can also combine several of the previous observed properties into one property that combines all the results:

This will result in this test output:

Ok, passed 100 tests.
7% "Values together: 3", Smaller than '1000'.
5% "Values together: 2", Smaller than '1000'.
5% "Values together: 0", Smaller than '1000'.
4% "Values together: 13", Smaller than '1000'.
4% "Values together: 1", Smaller than '1000'.
3% "Values together: -8", Smaller than '1000'.
3% "Values together: -4", Smaller than '1000'.
3% "Values together: -15", Smaller than '1000'.
3% "Values together: -12", Smaller than '1000'.
2% "Values together: 9", Smaller than '1000'.
2% "Values together: 8", Smaller than '1000'.
2% "Values together: 7", Smaller than '1000'.
2% "Values together: 27", Smaller than '1000', Bigger than '10'.
2% "Values together: 22", Smaller than '1000'.
2% "Values together: 1", Smaller than '1000', Bigger than '10'.
2% "Values together: -56", Smaller than '1000'.
2% "Values together: -3", Smaller than '1000'.
2% "Values together: -11", Smaller than '1000'.
2% "Values together: -10", Smaller than '1000'.
...

Combined Properties

The previous properties all had the same thing in common: they are  testing a single condition. What if we want to test multiple conditions? And how do we distinguish each property from one another?

Sometimes, we want to test two conditions. Combining them in a ‘AND’ expression. FsCheck also has this as extension method:

We can also add a ‘Label’ which is the same as the ‘usermessage’ in the ‘Assert’ class in the xUnit package: it pops up when the condition isn’t met.

By using this approach, we always know which property has failed.

Note that I now use a ‘NonNegative’ type instead of a regular int. This is also part of the FsCheck framework and allows me to make sure I always get a positive integer without specifying it in a Conditional Property. As you have seen, FsCheck will try any value that acts as a valid type; so, if I would add a condition to my property stating that I want a positive integer, I’ll get roughly the half of the test runs. This way, by using the ‘NonNegative’ I’m sure that I still get my 100 test runs without skewing the input so much I get merely any test runs.

Of course, we can also combine our properties in an ‘OR’ expression with the extension method ‘Or()’.

 Types

We’ve already seen an example with the previous properties where I used the ‘NonNegative’ type. FsCheck has several types that you can use to stricken our input. Some interesting ones:

  • PositiveInt represent an integer bigger than zero
  • NonZeroInt represent an integer which isn’t zero
  • NonNegativeInt represent an integer which isn’t below zero
  • IntWithMinMax represent an integer that can contain the int.Min and int.Max values
  • NonNull<T> wraps a type to prevent null being generated
  • NonEmptyArray<T> represent an array which isn’t empty
  • NonEmptySet<T> represent a set which isn’t empty
  • NonEmptyString represent a string which isn’t empty
  • StringNoNulls represent a string without null characters (‘\000’)
  • NormalFloat represent a float which isn’t infinite or NaN
  • Interval represent an integer interval
  • IPv4Address represents an IPv4 Address
  • IPv6Address represents an IPv6 Address

And many more... Don’t hesitate to come up with your own generic types that you can contribute to FsCheck!

We can also generate our own domain models with invalid and valid ones and use FsCheck to generate them for use; but that would lead us to another topic about generators.

Conclusion

In this post, we’ve seen how Property-Based Testing isn’t just a functional concept but an idea we can use in any language. FsCheck is inspired from the QuickCheck variant in Haskell, there’s also the ScalaCheck in Scala, JavaQuickCheck for Java, ClojureCheck for Clojure, JSVerify for JavaScript, … and so many more.

I’m not saying that you can abandon all your Example-Based Tests. Just like I stated in the beginning of this post: people think in examples. So, I think the combination of Example-Based Tests and Property-Based Tests is the sweet spot. By examples we can show the next person concrete ways of how to use your API and with properties you ensure that the implementation is the right one tested with any boundary conditions.

Thanks for reading!

Categories: Technology
Tags: Code Quality
written by: Stijn Moreels

Posted on Wednesday, September 27, 2017 11:49 AM

Toon Vanhoutte by Toon Vanhoutte

When using the Microsoft Azure stack, an important aspect is to use the right service for the job. In this way, you might end up with an API that is composed of several Azure services such as Blob Storage, Logic Apps and Azure Functions. In order to publish such an API in a unified way, you can leverage Azure Functions Proxies.

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

Categories: Azure
Tags: Functions
written by: Toon Vanhoutte