While I was waiting for a Firewall Change today, I thought: "Dude, learn something new!".

So, after playing around a lot with web APIs, web frameworks etc. I finally found
Eve.

When God created Eve, Python was already there!

'Eve' is a python web framework, based on Flask, especially made for RESTful Webservices.

During the last years, I wrote a lot of WebAPIs, mostly XMLRPC based, but I also used Ruby On Rails for RESTFul Webservices. Honestly that was overload.

Back to 'Eve'.

Eve is beautiful, easy, and simple to use.

Example:

#!/usr/bin/env python
-*- coding: utf-8 -*-

import sys  
from my_settings import SETTINGS

try:  
    from eve import Eve
except ImportError as e:  
    print(e)
    sys.exit(1)

if __name__ == '__main__':  
    app = Eve(settings=SETTINGS)
    app.run()

{% endcodeblock %}

{% codeblock my_settings.py lang:python %}
# -*- coding: utf-8 -*-
"""
settings.py  
"""

SETTINGS = {  
    'MONGO_HOST': 'localhost',
    'MONGO_PORT': 27017,
    'MONGO_DBNAME': 'linkit',
    'API_VERSION': 'v1',
    "URL_PREFIX": 'api',
    "X_DOMAINS": '*',
    "X_HEADERS": '*',
    'DOMAIN': {'links': {
        'resource_methods': ['GET', 'POST'],
        'schema': {
            'link_title': {
                'type': 'string',
                'minlength': 1,
                'maxlength': 4096,
            },
            'link_url': {
                'type': 'string',
                'minlength': 1,
                'maxlength': 4096,
            }
        }
    }}
}

As you can see, most of the configuration is done in the my_settings.py file.
It defines the mongodb server, the mongo database name, etc.

So if you run this script now, you can actually fire up curl, and get this result (I already have something in my DB):

curl -i http://127.0.0.1:5000/api/v1/links  
HTTP/1.0 200 OK  
Content-Type: application/json  
Content-Length: 4927  
Last-Modified: Wed, 13 Nov 2013 16:15:14 GMT  
Server: Eve/0.2-dev Werkzeug/0.9.4 Python/2.7.6  
Date: Wed, 13 Nov 2013 16:43:46 GMT

{"_items": [{"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 11:52:43 GMT", "created": "Wed, 13 Nov 2013 11:52:43 GMT", "link_url": "http://www.heise.de/", "etag": "3be7ff5a33800231c01b3ae6a02a7c3ff4515d69", "_links": {"self": {"href": "/links/5283680b8322c7417749a956", "title": "Link"}}, "_id": "5283680b8322c7417749a956"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 11:55:31 GMT", "created": "Wed, 13 Nov 2013 11:55:31 GMT", "link_url": "http://www.heise.de/", "etag": "f53768d84db3c1ceaf5c786732fed0e24d280ea4", "_links": {"self": {"href": "/links/528368b38322c7417749a957", "title": "Link"}}, "_id": "528368b38322c7417749a957"}, {"link_title": "Hello 2", "updated": "Wed, 13 Nov 2013 11:55:31 GMT", "created": "Wed, 13 Nov 2013 11:55:31 GMT", "link_url": "http://www.golem.de/", "etag": "70ead6d313d11d189b64a1a9dd2aaf3832fa7e25", "_links": {"self": {"href": "/links/528368b38322c7417749a958", "title": "Link"}}, "_id": "528368b38322c7417749a958"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 11:55:37 GMT", "created": "Wed, 13 Nov 2013 11:55:37 GMT", "link_url": "http://www.heise.de/", "etag": "482120452fdabd99401f87d550f082972ad31d87", "_links": {"self": {"href": "/links/528368b98322c7417749a959", "title": "Link"}}, "_id": "528368b98322c7417749a959"}, {"link_title": "Hello 2", "updated": "Wed, 13 Nov 2013 11:55:37 GMT", "created": "Wed, 13 Nov 2013 11:55:37 GMT", "link_url": "http://www.golem.de/", "etag": "f214f062b087323298d19535589393e34e12e9ce", "_links": {"self": {"href": "/links/528368b98322c7417749a95a", "title": "Link"}}, "_id": "528368b98322c7417749a95a"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 16:14:13 GMT", "created": "Wed, 13 Nov 2013 16:14:13 GMT", "link_url": "http://www.heise.de/", "etag": "56efc32ed92388487a7b1d5e4c8f941fdc6ef3c9", "_links": {"self": {"href": "/links/5283a5558322c74a4eed3574", "title": "Link"}}, "_id": "5283a5558322c74a4eed3574"}, {"link_title": "Hello 2", "updated": "Wed, 13 Nov 2013 16:14:13 GMT", "created": "Wed, 13 Nov 2013 16:14:13 GMT", "link_url": "http://www.golem.de/", "etag": "31f9afd2bec13b5c8e2f0db65a99754b099e0efe", "_links": {"self": {"href": "/links/5283a5558322c74a4eed3575", "title": "Link"}}, "_id": "5283a5558322c74a4eed3575"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 16:14:14 GMT", "created": "Wed, 13 Nov 2013 16:14:14 GMT", "link_url": "http://www.heise.de/", "etag": "6c7d5e6fc1f96e7d80281753ccd9031c7e30ba6a", "_links": {"self": {"href": "/links/5283a5568322c74a4eed3576", "title": "Link"}}, "_id": "5283a5568322c74a4eed3576"}, {"link_title": "Hello 2", "updated": "Wed, 13 Nov 2013 16:14:14 GMT", "created": "Wed, 13 Nov 2013 16:14:14 GMT", "link_url": "http://www.golem.de/", "etag": "161fe88f36fbff8ec7e5e19f4c157320baee57fa", "_links": {"self": {"href": "/links/5283a5568322c74a4eed3577", "title": "Link"}}, "_id": "5283a5568322c74a4eed3577"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 16:14:14 GMT", "created": "Wed, 13 Nov 2013 16:14:14 GMT", "link_url": "http://www.heise.de/", "etag": "d125e1c1be58d65d8d8323740e0c3f1b0c83bb7d", "_links": {"self": {"href": "/links/5283a5568322c74a4eed3578", "title": "Link"}}, "_id": "5283a5568322c74a4eed3578"}, {"link_title": "Hello 2", "updated": "Wed, 13 Nov 2013 16:14:14 GMT", "created": "Wed, 13 Nov 2013 16:14:14 GMT", "link_url": "http://www.golem.de/", "etag": "664a0196b756a1806854747d2196e2b812ec6887", "_links": {"self": {"href": "/links/5283a5568322c74a4eed3579", "title": "Link"}}, "_id": "5283a5568322c74a4eed3579"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 16:14:56 GMT", "created": "Wed, 13 Nov 2013 16:14:56 GMT", "link_url": "http://www.heise.de/", "etag": "5cb3e7a05f87ff7e2fceeb47a499683077119999", "_links": {"self": {"href": "/links/5283a5808322c74a4eed357a", "title": "Link"}}, "_id": "5283a5808322c74a4eed357a"}, {"link_title": "Hello 2", "updated": "Wed, 13 Nov 2013 16:14:56 GMT", "created": "Wed, 13 Nov 2013 16:14:56 GMT", "link_url": "http://www.golem.de/", "etag": "ca978b6ebba3c7a3193466255b6768bbd5f1e60f", "_links": {"self": {"href": "/links/5283a5808322c74a4eed357b", "title": "Link"}}, "_id": "5283a5808322c74a4eed357b"}, {"link_title": "Hello 1", "updated": "Wed, 13 Nov 2013 16:15:14 GMT", "created": "Wed, 13 Nov 2013 16:15:14 GMT", "link_url": "http://www.heise.de/", "etag": "b32872de1fef61bb8ea8c002c8ca278e89656f0d", "_links": {"self": {"href": "/links/5283a5928322c74a4eed357c", "title": "Link"}}, "_id": "5283a5928322c74a4eed357c"}, {"link_title": "Hello Stephan T.", "updated": "Wed, 13 Nov 2013 16:15:14 GMT", "created": "Wed, 13 Nov 2013 16:15:14 GMT", "link_url": "http://www.golem.de/", "etag": "279cdfb01ed7a3e59a767f7e630c0a4c7455e9f8", "_links": {"self": {"href": "/links/5283a5928322c74a4eed357d", "title": "Link"}}, "_id": "5283a5928322c74a4eed357d"}], "_links": {"self": {"href": "/links", "title": "links"}, "parent": {"href": "/api/v1", "title": "home"}}}

Pretty simple, isn't it?
Right now, there are only two HTTP Verbs supported, GET and POST.
GET for retrieving the collection of links and when you pass an ID to the URL, you only get one link document.
POST for adding a document to the links collection.

You can do more, and Eve gives you a good amount of configuration options to secure your API.

But this was too simple, wasn't it?

Now playing Dart(s)

Praise da Google Empire!

Google created Dart, a simple, but powerful new language for the Web.
If you know C, C++, Java and JavaScript you are glad to hear, that Dart is really easy to learn.

So, given my Python Eve example above, let's build a simple webpage, which displays the result inside your favorite browser.

First step will be to download your Dart Language Development Environment:

Head over to Dart: Get Started and download your favorite environemnt.

Now, start it and create a new application, name the application (for this example): LinkIt

You will see several folders with code. The most important part is under the web folder.

You will find three files:

  • linkit.css
  • linkit.html
  • linkit.dart

In my simple example, I am using Bootstrap 3 and JQuery as CSS/UI Framework.
So get it and move bootstrap directories and files to the web folder.

You should have something like shown in the picture:

Dart IDE File View

Now, let's work on the linkit.html first:

Replace the contents of the file with this code:

<!DOCTYPE html>

<html>  
  <head>
    <meta charset="utf-8">
    <title>LinkIt</title>
    <link rel="stylesheet" href="linkit.css">
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <style>
      BODY {
        margin-top: 60px;
      }
    </style>
  </head>
  <body>
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Home</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </div>
    <div class="container">
      <div class="row">
        <div class="col-lg-12">
          <table class="table table-bordered" id="link-table">
            <thead>
              <tr>
                <th>Title</th>
                <th>URL</th>
              </tr>
            </thead>
          </table>
        </div>
      </div>
    </div>
    <script type="application/dart" src="linkit.dart"></script>
    <script src="packages/browser/dart.js"></script>
    <script src="js/jquery.js"></script>
    <script src="js/bootstrap.min.js"></script>
  </body>
</html>  

This will create a simple menubar, adjust the top margin of the body, to show the container directly under the NavBar and includes all necessary stylesheets and javascripts and of course the dart script.

We will focus on the table element with its ID: 'link-table'.

What we want:

  • catch the table element
  • create a table body element
  • add rows to the table body and
  • inside the row, add two cell elements.

Furthermore we want

  • Read the data from the python-eve backend, we created before,
  • convert the returned json data into Dart readable variable instances
  • output the result data in the cells.

Nothing is easier than that.

Switch to linkit.dart and replace the contents with this:

import 'dart:html';  
import 'dart:convert';

class LinkTable {  
  TableElement linkTable;
  TableSectionElement linkTableBody;
  TableRowElement row;
  TableCellElement cell;

  LinkTable(var sel) {
    this.linkTable = query("#link-table");
    this.linkTableBody = linkTable.createTBody();  
    this.readLinksData();
  }

  void readLinksData() {
    var xhr = new HttpRequest();
    xhr
    ..open('GET','http://127.0.0.1:5000/api/v1/links/')
    ..onLoadEnd.listen((e) => requestComplete(xhr))
    ..send('');
  }
  requestComplete(HttpRequest request) {
    Map parsedMap = JSON.decode(request.responseText);
    print(parsedMap['_items'].length);
    for (var item in parsedMap['_items']) {
      this.row=linkTableBody.addRow();
      this.cell = this.row.addCell();
      this.cell.text=item['link_title'];
      this.cell = this.row.addCell();
      this.cell.text=item['link_url'];
    }
  }
}


void main() {  
  new LinkTable("#link-table");
}

I don't want to comment this source, because it should be directly understandable.

Now, run this application, there will be a Chromium browser started, and you can see the result (hopefully you started the python eve backend first ;))

And if this is not enough for you, the good guys from AngularJS ported their awesome JavaScript framework to Dart.

You can find it Angular for Dart here.

Enjoy!!!