Let’s Make REST Into a Protocol
Tags: Programming, Microservices, Django, Functional Programming, Python

Let’s Make REST Into a Protocol

“I have wrested the rest of the REST out of my hands and put it all to rest with the rest of the REST on the shelf, where it all can rest.”, circa. 2021.

What is a Protocol?

HTTP 1.1 is a Protocol.

If you want to use HTTP 1.1 you simply use a component like an HTTP 1.1 Web Server to serve your content. Then you use an HTTP 1.1 Browser to consume your content. Did you have to code HTTP 1.1 to do any of this? Nope. HTTP 1.1 as a protocol was coded for you by someone or likely a number of someones you never met. This is the beauty of using an existing Protocol. It just works. And you get to use it. And by now it has been accepted by everyone.

Why has REST never achieved this same status?

Why are so many programmers blindly coding all that REST Interface goop over and over and over?

Every single part of every single REST API is 100% the same except for the function dangling at the end of each and every RESTful Endpoint. And still in 2020 REST has not been elevated into being just a Protocol like HTTP 1.1, for instance. Why? Or better, Why not?

Introducing the Dynamic Pluggable Microservice Framework

This is a pre-coded Framework you can use, right now, to publish all your Microservices or Web Services with very little effort and very little code.

This Dynamic Pluggable Microservice Framework could make REST into a full-fledged Protocol.

Why waste all that time coding URL Specs?

What is a URL Spec? Huh?

This is a typical set of URL Specs for one of the more popular Web Frameworks known as Django:

from django.urls import include, path



urlpatterns = [

path('index/', views.index, name='main-view'),

path('bio/<username>/', views.bio, name='bio'),

path('articles/<slug:title>/', views.article, name='article-detail'),

path('articles/<slug:title>/<int:section>/', views.section, name='article-section'),

path('weblog/', include('blog.urls')),

...

]

Now if you had a bunch of REST Web Services to publish you would have to code one of these “path” statements for each and every endpoint, each and every function you wanted to expose to the REST Protocol. This might be a lot of work to code and maintain. How well do you know regex, anyway? Is this how you want to spend your professional time as a programmer? Is this where you want to spend your money as an Organization or Company? This is only part of the work required to get your REST Web Services up and running.

But wait, there’s more code to write.

Consider the following blob of code:

@api_view(['GET', 'POST', 'DELETE'])

def tutorial_list(request):

# GET list of tutorials, POST a new tutorial, DELETE all tutorials





@api_view(['GET', 'PUT', 'DELETE'])

def tutorial_detail(request, pk):

# find tutorial by pk (id)

# GET / PUT / DELETE tutorial





@api_view(['GET'])

def tutorial_list_published(request):

# GET all published tutorials

These are actual functions that could be exposed to REST but so far you have not even begun to head in that direction yet. There is so much more to do when coding a RESTful Interface. So much to do and so little time.

There is an easier way to do this

You could use the Dynamic Pluggable Microservice Framework.

Take a look at a simpler way to get your functions exposed to REST by clicking here.

Sample code:

Step 1: Import the Python decorator.

from vyperlogix.decorators import expose

Step 2: Expose your function as a REST endpoint.

@expose.endpoint(method=’GET|PUT|POST’.split(‘|’), API=’hello-world’) def foo(*args, **kwargs): return {‘response’: ‘hello-world’}

This makes the function “foo” into a REST endpoint via the “GET, PUT and POST” HTTP 1.1 Methods. The “foo” function will be accessed via the API name of “hello-world” rather than the name “foo” however both can be used interchangeably. The function “foo” will return some data that will be magically turned into JSON for you with no need to be concerned about serializations. You will however need to ensure all the data you want to return via JSON is composed of simple data types but this is how JSON works.

Step 3: Plug-in your Python Module.

Take a look at the plugins directory here.

There is no need to restart the webserver when you plugin a new Module. This is all 100% dynamic. This means you can deploy a Development REST Server so you can do your development work. Then deploy a Staging REST Server where you can test your deployable REST APIs. Then deploy a Production REST Server where your customers will consume your REST API. Your CI/CD Pipeline will simply copy your Python Modules into the “plugins” directory for each environment and you can immediately test or use your exposed APIs with no downtime. Easy, huh?

How do I use this newly exposed REST endpoint, anyway?

Take a look at the sample unit tests for this framework by clicking here.

Take a look at a simpler test environment by clicking here. This “rest.http” file is more useful when you use vscode and the REST Client extension. And “yes” vscode extensions are dynamic plugins. See how useful modern programming techniques can be in the 21st Century? Even Microsoft knows how to leverage dynamic pluggable frameworks which is exactly what vscode is.

Get a directory of your plugins.

Notice that the URL Spec of “/rest/services/__dir__/” is baked into this framework.

What you get from this is some nice-looking JSON that shows you everything you need to know about your plugins.

Let’s use one of our sample APIs from the framework distro

This calls the “/hello-world” API that has been exposed via the “foo” function.

Notice the URL Parameters “/1/2/3/4/5/6/7/8/9/10/”. These parameters are elastic and configurable with either default names, configurable names or mappable names. Do some of your REST APIs use up to 1000 Parameters? No problem, this framework handles all that.

Notice the Query Parameters “a=1&b=2&c=3&d=4”. These parameters are also elastic which means you can issue any number of them but this is built into the HTTP 1.1 Protocol.

How do these Parameters get into your function “foo” ? This is done via the **kwargs. In Python “**kwargs” is a dictionary of keys and values. All those named URL Parameters and Query Parameters get mixed into a single dictionary and you can consume them at runtime via the “**kwargs”. Take care not to reuse the same Parameter names in the form of Query Parameter names or you may lose some values but again, this is how this framework works.

Module Aliases and API Versioning

The following issues the very same REST API call using the Module Alias for module1.py:

This is the same as the following:

This means you can build and deploy versioned APIs for your users. The Module Alias can be a version identifier or the module filename can be a version identifier.

URL Parameter Mapping

This only works for HTTP 1.1 Methods other than “Get”.

This remaps the first 10 URL Parameters to use a dynamic set of names at runtime. Again this is configurable. This means you can use your own sets of URL Parameter names for your specific APIs the way you want to use them. This also makes your exposed modules more self-documenting especially if you were to add a docstring to each exposed function. Now you can generate programmer’s docs for your modules using existing Python tools. Self-documenting code.

Private Functions or Private Variables

What if you want to embed private functions in your exposed modules?

Easy.

Private functions are those beginning with “__” or those that are not exposed via the “expose.endpoint” decorator.

Python classes and variables are not exposed and not exposable unless you do so via an exposed endpoint.

You can also build and deploy your own Python Packages and put them on your own Python Path and then use them from your exposed endpoints using this Framework. You could plugin Modules that do not expose endpoints but doing so is not beneficial.

Click here to read more.

REST has become a Protocol

You should be able to see how REST has become a Protocol much like HTTP 1.1 became a Protocol.

Automate your RESTful APIs by using this Dynamic Pluggable Microservice Framework.

Automate your URL Specs. Don’t waste your time coding them.

Automate JSON. Don’t waste your time using JSON Libraries, this has been done for you.

Automate API Versioning. Don’t waste your time building this code yourself.

Want to see this framework in action via a Docker Container? Click here.

docker pull raychorn/microservices-framework:0.7.0

This container has all the required modules. Update the git clone and give it a whirl.

Want to add functionality to this framework?

Become a sponsor and make new feature requests.