In the last few days, I finally found the time to get in touch with Python a bit. The programming language is known to be very widespread and offers almost infinite possibilities besides PowerShell-style automation, data science and web development…. In the area of Business Central, some people might know it in the context of Docker.
But I always find it difficult to learn things according to instructions or literature. The best way for me is to take a concrete problem and try to solve it. In this case, I did learn some of the absolute basics from the book “Python Crash Course – A Hands on”, but then switched to solving my defined problem… a Python REST API-Template.
So, here is my approach to learning a little bit of python. Feel free to comment on it as I am absolutely sure it‘s far away from being optimal 🙂
You can find the complete Python REST API-Template on my GitHub Page.
The Problem
In the course of my work and the evolution of Business Central, especially in the cloud, microservices, among other technologies, are becoming increasingly important… i.e. the encapsulation of specific (or unsolvable in AL) tasks into APIs, which can then be consumed via REST calls. I have already written a couple of productively used microservices for our Addons based on Azure Functions in C# as well as Node.JS. However, the elegance and readability of Python has always appealed to me.
The Goal
My goal for the learning session here was to create a reusable template for a REST API, which I can “fill with life” at will afterwards by extending it with the concrete functions. It should then be running as an Azure App Service, at best with an automatic build-pipeline. The template should have the following properties and requirements:
- Build on the versatile and easy-to-use Flask Framework
- Basic Authentication using Azure Cosmos DB (MongoDB)
- API versioning using Flask Blueprints
- Settings saved in env variables
Implementing the Requirements
Settings
An uncomplicated way to store your settings data is using environmental variables. In your Visual Studio Code environment, you simply create an .env file and add your settings to is. Afterwards, you’re able to access them wherever you want using the “os.environ.get(‘TEST_ENV_VAR’)” method:
|
|
And the most charming thing with these environmental variables is, that we could access the Azure App Service settings the same way without changing anything:
API versioning using Blueprints
Although I know it’s usually not a best practise in API development, I wanted to implement versioning in the template. I want to be able to serve i.e. newer or breaking changes through new versions. Fortunately, Flask gives you the Blueprint approach. With these blueprints, you could register your different versions to your routes.
To achieve this, the structure of your project should be setup properly. Simplified, my project looks like this:
- api
- common (used by all versions)
- functions.py
- authy.py
- mongo.py
- v1 (blueprint & version specific)
- functions.py
- routes.py
- v2-n (blueprint & version specific)
- functions.py
- routes.py
- app.py (register blueprints and initiate flask)
- common (used by all versions)
First, we create the blueprint for every version needed. Here we could now implement all our functionality we need in the API:
|
|
After that, in our app.py, we import all blueprints/versions and register them with a URL prefix:
|
|
Access to the API is then possible through the defined URLs:
Basic Authentication
For our goal to use basic authentication with our API we use the build-in HTTPBasicAuth() class. And within this implementation we override verify_password() with our own procedures. As we would like to get the credentials from an Azure Cosmos DB, we fetch it from there and check it against the given, hashed credentials.
|
|
Routes to be authenticated could then be easily protected with one line of code. The methods that require authentication can be decorated with the login_required decorator:
|
|
Accessing Azure Cosmos DB
As we already mentioned in the authentication part, we use an Azure Cosmos DB for storing data… in this case our users’ credentials. I didn’t really get along with Microsoft’s azure-cosmos library. So I use the pymongo implementation for that I found some nice examples:
|
|
Deployment of the Python REST API-Template
For this example, I looked at the deployment functions in Azure App Services. Here you have the option of choosing a GitHub repository and a branch. As soon as the branch is updated, the app service automatically updates itself from this repository:
In your GitHub repo’s actions, you could now watch the build pipeline run. Crazy simple and intuitive:
I’m really looking forward for the first productive requirements where I could use it. I find it far more readable and intuitive than, for example, Node.JS. However, one must be aware that the latter is more suitable for certain requirements due to its speed and performance.
You can find the complete Python REST API-Template on my GitHub Page.