Eve REST API Framework v0.6.2 is out

Today I released Eve 0.6.2. It includes many fixes and improvements over the previous releases. Areas addressed are CORS management, soft deletes, token authentication, oplog, data validation, and others. Please see the changelog for details.

Work on v0.7 is also ongoing. It will include new features such as support for the MongoDB Aggregation Framework (docs) and a few breaking changes, so you might want to check it out in advance.

Special thanks to Arnau Orriols, Cyril Bonnard, Hamdy, Luca Di Gaspero, Manquer, Nick Park, Patrick Decat, Prayag Verma, Ralph Smith, Stratos Gerakakis, Valerie Coffman and Wei Guan who contributed to this release.

Real Life .NET Cross Platform

There is a new episode up at Channel9 TecHeroes. It is called Real Life .NET Cross Platform and it is about developing production-ready, cross-platform applications with today’s .NET. In the interview we talk about SimpleCache, an asynchronous, permanent and cross-platform key-value object cache powered by SQLite3. The project is still a work in progress so there is no NuGet package available yet, but it is quite usable already. The talk slides are also available.

Look mum, I’m a MVP

A few hours ago I was notified that I have been awarded with the Microsoft MVP Award for Development Technologies.

This came totally unexpected. Especially so considering that during the last few years I have been splitting my time between Microsoft and other open source technologies. My public work has mostly been on Python and MongoDB. Yes I also released .NET open source projects in the meantime (more are coming soon) and yes, I wrote a few articles here and on the MSDN Blog, attended Microsoft events and did interviews. But really, I did not expect these activities to have an impact. This is probably why only a couple minutes from learning about the award I was suffering Impostor Syndrome symptoms.

Now however, as I ponder on the whole issue a little bit, I start to realise how this could probably make (at least some sort of) sense. New Microsoft has been eager to catalyse attention and interest from the open source community and, in a broader sense, from people not yet accustomed to the brand. In light of this, people who have been active in communities other than Microsoft’s and have also been exposed to different technologies, mindsets and approaches to common IT problems could indeed offer some value. Or at least that’s how I am reading it right now.

So a new chapter is unfolding in my twenty-five years long love/hate relationship with Microsoft. It is my intent to live up to this award, for which I am very grateful.

My talk at Percona Live 2015

The slides of my talk at Percona Live 2015 (Amsterdam) are online. It was titled “MongoDB and REST APIs a Match Made in Heaven” and it was meant as an introduction to Mongo, REST principles and the Eve python framework.

Overall it has been a pleasant experience, although I found that splitting 300 attendees through seven concurrent tracks ultimately led to too much fragmentation. People often found themselves with 2-3 interesting talks all happening simultaneously, and just had to pick one.

I could only stay one day so I missed all side events, speakers dinner included, which was a bummer.

Custom endpoint handlers with Eve

On Stack Overflow and the Eve mailing list, but also in my mailbox and even on Twitter, I get a lot of enquiries on how to build custom endpoints within a Eve-powered RESTful application. Now, since within Eve all endpoints are fully customizable, what they really mean is:

How do I setup endpoints without any binding to a data entity, just connected to a custom method?

They would like to call something like /mycustomendpoint and get the response from a method they have defined somewhere in the Python sources. The standard endpoint-entity mapping provided by Eve covers 90% of their needs, but sometimes they just need endpoints that have nothing to do with data entities.

This is very easy to achieve. I’m writing it down so I can point people to this post in the future.

Eve is Flask

Eve is a Flask application and I really mean it since it is, in fact, a Flask subclass. Eve adds out-of-the-box RESTful capabilities to the Flask micro-framework. Most of the time you will be happy with just Eve’s own features but remember, the full Flask (and Werkzeug at a lower level) features set is also part of your arsenal.

Whatever you can do with Flask, you can do with Eve

So yes, of course you can easily set some functions to be invoked when a custom endpoint is hit with a request. The following snippet is a slightly modified version of Flask’s very own Quickstart tutorial:

from eve import Eve
app = Eve()

@app.route('/hello')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

By decorating the hello_world method with the route decorator we added a new endpoint to the application. Each time a request to /hello comes in, it will be routed to our custom method. Of course the regular API endpoints (either defined in settings.py, passed as a dict at launch, or registered live by calling the register_resource method) will also be available.

If you have an Eve authentication class securing regular API endpoints, you can apply it to your custom endpoint too. Just add a requires_auth decorator:

from eve.auth import requires_auth

@app.route('/hello')
@requires_auth('resource')
def hello_world():
    return 'Hello World!'

Say that you saved the above snippet as run.py and also have your RESTful endpoints properly configured. Launch the script:

$ python run.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C ...)

You can now point your browser to http://localhost:5000/hello/ and enjoy the application greeting. Or you can consume any other configured API endpoint.

As all of Flask features are at your fingertips you might as well opt for registering a blueprint, which is what the awesome Eve-Docs extension is doing in order to provide a static HTML /docs endpoint on top of any Eve powered API.

Cerberus 0.9 has been released

A few days ago Cerberus 0.9 was released. It includes a bunch of new cool features, let’s browse through some of them.

Collection rules

First up is the new set of anyof, allof, noneof and oneof validation rules. anyof allows you to list multiple sets of rules to validate against. The field will be considered valid if it validates against one set in the list. For example, to verify that a property is a number between 0 and 10 or 100 and 110, you could do the following:

>>> schema = {
...     'prop1': {
...         'type': 'number',
...         'anyof': [
...             {'min': 0, 'max': 10}, 
...             {'min': 100, 'max': 110}
...         
...         ]
...     }
... }

>>> doc = {'prop1': 5}
>>> v.validate(document, schema)
True

>>> doc = {'prop1': 105}
>>> v.validate(document, schema)
True

>>> doc = {'prop1': 55}
>>> v.validate(document, schema)
False

allof is the same as anyof, except that all rule collections in the list must validate. Same pattern applies to noneof (no rule in collection must validate) and oneof (only one rule in collection must validate).

Type coercion

Type coercion allows you to apply a callable to a value before any other validators run. The return value of the callable replaces the new value in the document. This can be used to convert values or sanitize data before it is validated.

>>> v = Validator({'amount': {'type': 'integer'}})
>>> v.validate({'amount': '1'})
False

>>> v = Validator({
...     'amount': {
...         'type': 'integer', 
...         'coerce': int
...     }
... })
>>> v.validate({'amount': '1'})
True
>>> v.document
{'amount': 1}

>>> to_bool = lambda v: v.lower() in ['true', '1']
>>> v = Validator({
...     'flag': {
...         'type': 'boolean', 
...         'coerce': to_bool
...     }
... })
>>> v.validate({'flag': 'true'})
True

>>> v.document
{'flag': True}

Properties (keys) validation

propertyschema is the counterpart to valueschema (also new, it replaces the now deprecated keyschema) and validates the keys of a dictionary.

>>> schema = 'a_dict': {
...     'type': 'dict', 
...     'propertyschema': {
...         'type': 'string', 
...         'regex': '[a-z]+'
...     }
... }

>>> document = {'a_dict': {'key': 'value'}}
>>> v.validate(document, schema)
True

>>> document = {'a_dict': {'KEY': 'value'}}
>>> v.validate(document, schema)
False

List of types

The type rule can now be a list of types, to allow for different type of values for the field.

>>> v = Validator({
...     'quotes': {
...         'type': ['string', 'list']
...     }
... })

>>> v.validate({'quotes': 'Hello world!'})
True

>>> v.validate({'quotes': ['Do not disturb my circles!', 
...                        'Heureka!']})
True

>>> v = Validator({
...     'quotes': {
...         'type': ['string', 'list'], 
...         'schema': {'type': 'string'}
...     }
... })

>>> v.validate({'quotes': 'Hello world!'})
True 

>>> v.validate({'quotes': [1, 'Heureka!']})
False

>>> v.errors
{'quotes': {0: 'must be of string type'}}

And there is more so make sure you check the changelog before upgrading. No breaking changes but there’s at least one deprecation, as mentioned.

Fun fact: Cerberus is currently getting 3x the downloads of his sister project Eve, the REST API Framework for which the tool was originally conceived. Interesting if you consider that Eve is featuring 10x the GitHub stars. Fun, but not really surprising since Cerberus probably has a broader audience.

Special thanks to Frank Sachsenheim, Tobias Betz, Brett and C.D. Clark III for their valuable contributions to this release.

If you want to get in touch, I am @nicolaiarocci on Twitter.

Monolith vs Microservices

I spent the last couple days in Paris with a bunch of smart architects and developers who are about to deal with a complex Monolithic-to-Microservices architecture transition.

On my flight back to Italy I jotted down a few thoughts on the topic and then, this morning, the first thing that comes up on my newsfeed is Monolith First by Martin Fowler. Stunning, because the essay content totally resonates with my own notes, so much that it would perfectly serve as a recap for them.

Going directly to a microservices architecture is risky, so consider building a monolithic system first. Split to microservices when, and if, you need it.

And also, perhaps more importantly:

A more common approach is to start with a monolith and gradually peel off microservices at the edges. Such an approach can leave a substantial monolith at the heart of the microservices architecture, but with most new development occurring in the microservices while the monolith is relatively quiescent.

I find it fascinating that there is a chance that my notes and the essay were written (by astral coincidence?) in the very same minutes.