This project is able to generate Policies for Azure API Management from fluent interface written in .Net Core WebAPI application.
Azure API Management is an implementation of API Gateway pattern on Azure. APIs are defined by API templates which consist of OpenAPI Specification (Frontend) and Policies (Backend). Policies are XML based rules which describes behavior of the endpoint for incoming requests. Each endpoint has its own policy and there is also policy applicable to all endpoints in the API.
Target of this project is to provide easy, programmatic and safe way how to write the policies.
Let’s have this simple policy (change url, change uri, cache result):
<policies>
<inbound>
<base />
<set-backend-service base-url="https://contonso.com" />
<rewrite-uri template="api/v1" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
<cache-store duration="5" />
</outbound>
<on-error>
<base />
</on-error>
</policies>
You can describe it with PolicyBuilder like this:
PolicyBuilder
.Inbound(builder => builder
.Base()
.SetBackendService("https://contonso.com")
.RewriteUri("api/v1")
.Create())
.Backend(builder => builder
.Base()
.Create())
.Outbound(builder => builder
.Base()
.CacheStore(TimeSpan.FromSeconds(5))
.Create())
.OnError(builder => builder
.Base()
.Create());
And with using available extensions, you can simplify it like this:
PolicyBuilder
.Inbound(builder => builder
.Base()
.SetBackendAndRewriteUri("https://contonso.com", "api/v1"))
.Backend()
.OutboundWithCaching(TimeSpan.FromSeconds(5))
.OnError();
The basic idea is having a WebAPI project which represents the API Gateway. Each endpoint (action method) can have policy builder as its implementation. Policy builder itself describes policy through a fluent interface. The builder is resolved in runtime and XML policies are auto-generated into files. Generated policies can be stored in your repository or uploaded to an APIM instance.
Endpoint with policy builder can look like this:
[HttpPost]
public void Post(string forecast)
{
_policyBuilder.SetBackendAndRewriteUri("https://contonso.com", "api/v1");
}
-
Easy to start
It is more convenient for developers to describe an API endpoints in familiar IDE and .Net code base than in proprietary systems and code of Azure API Management.
-
Reusability
You can easily define your own methods or extensions which wraps common or repeated policy parts and maintain them on one place.
-
Removing vendor lock
You can switch implementation of the PolicyBuilder and create your own API Gateway implementation
-
Building release pipeline
Generated policies are stored in your repository and can be released to multiple instances of APIM (e.g. Test and Live)
-
Safe and testable
There is no way how to provide full testing of generated policies. But still the fluent interface and generator provides lot of building conditions and constraints to keep the output fully compatible with APIM.
-
Create your WebAPI project which will describe the API. You can use WebAPI template in VisualStudio. As an inspiration you can check our example project
-
Install PolicyBuilder generator Nuget package
Install-Package Oriflame.PolicyBuilder.Generator
-
Register PolicyBuilder generator to your
ServiceCollection
in yourStartup.cs
public void ConfigureServices(IServiceCollection services) { ... services.AddPoliciesGenerator(); }
-
Add Generator call
You can add this for example to
Program.cs
to generate your policy on application start.public static void Main(string[] args) { var host = CreateHostBuilder(args).Build(); var generator = host.Services.GetService(typeof(IGenerator)) as IGenerator; generator.Generate(@"APITemplates\ApiExample\policies", typeof(Program).Assembly); host.Run(); }
-
Inject
IPolicyBuilder
into your controller(s) to use PolicyBuilder and define your policies -
Run your project (Ctrl+F5 in VS) to generate policies
-
Policies can be uploaded to your APIM instance(s) using APIM Rest API
Except endpoints you can define All operations policy which is applicable to all API endpoints. You have to simply inherit AllOperationsPolicyBase
class. You can check our All Operations example class
For simplifying the builder code, you can use predefined extensions. Check example how they could be useful. And of course you can simply create your own.
Sometimes you need to use C# snippets for getting variables etc. especially for complex policies. PolicyBuilder contains small helpers which allows you simply define those snippets.
Example:
var backendUrlVariableName = "backendUrl";
PolicyBuilder
.Inbound(builder => builder
.Base()
.SetVariable(backendUrlVariableName, NamedValue.Get("Backend"))
.Create()
)
.Backend(builder => builder
.SetBackendService(ContextVariable.GetAsString(backendUrlVariableName))
.Base()
.Create())
.Outbound()
.OnError();
<policies>
<inbound>
<base />
<set-variable name="backendUrl" value="{{Backend}}" />
</inbound>
<backend>
<set-backend-service base-url="@((string)context.Variables["backendUrl"])" />
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
You can define easily your own release pipeline for whole API. You will need:
- Add Swagger for generating OpenApi spec.
- Connect your policies and OpenApi spec. by Operation Id by customizing
IOperationsProvider
- Write a script for uploading whole API Template to API Management
You can read more about defining release process in this article
If you need to access the controller method inside your implementation for a builder method, you can use ActionContextHelper
. It stores MethodInfo
in thread safe context.
This could be helpful when you need to get some a controller method attribute for example.
Policies in API Management are very rich functionality and not all combinations and options are currently available. Feel free to contribute and extend functionality of this project.