Quantcast
Channel: RDO Community Blogs » python
Viewing all articles
Browse latest Browse all 3

Build your RESTful API web-service in 5 minutes

$
0
0

As Software Developers , we sometimes need to create a simple server that can accept some REST queries without wasting too much time. It’s always appealing to build our own components as it ensures our needs will be met. While REST sounds basic and easy to implement, to get a full REST server working is not trivial, especially when you want shiny features like HATEOAS ( https://en.wikipedia.org/wiki/HATEOAS ), pagination support, query filter, multiple content type (JSON, XML, plain text, …) support, If-Match/ETag, etc.

Let me walk you through a simple way of doing this using Python-Eve and Eve-SQLAlchemy.

Python-Eve

Eve is an open source Python REST API framework designed for human beings. It allows to effortlessly build and deploy highly customizable, fully featured RESTful Web Services.

Eve is built on top of Flask and gives the ability to easily extend an existing application to add REST routes. Those routes are directly associated to “resources” objects. Eve is historically associated with MongoDB. The resources objects were MongoDB collections but it is now possible to use SQLAlchemy or ElasticSearch instead.

The framework comes with an impressive list of features that are well covered in the project documentation.

The goal of this example if to show how to prepare a REST microservice based on Python-Eve and a SQL database. To do so, we will create a lightweight application to trace hateful and trollish comments from social media sites. The idea is to provide a central database be able to spot the same comment on different web site or help the moderator to block users. We will first prepare a REST back-end that we will consume later from a JavaScript Interface.

Requirements

We will use PostgreSQL for this example but you can use any engine supported by SQLAlchemy. Let’s install it:

sudo dnf install postgresql-server

Our DB structure

We will now start your application. For the moment it will be a sole wsgi.py file and we will use python3. We will see later in another article how we can split the application in different files.

Eve-SQLAlchemy expects your DB tables to have a least these fields:

  • an unique ID
  • a creation date,
  • an update date and the Etag.

Those fields will be imported from a generic SQLAlchemy declarative_base class:

Base = declarative_base()
class CommonColumns(Base):
    __abstract__ = True
    _created = Column(DateTime, default=func.now())
    _updated = Column(DateTime,
                      default=func.now(),
                      onupdate=func.now())
    _etag = Column(String)
    _id = Column(Integer, primary_key=True, autoincrement=True)

 

We can now create our real class and register it in Eve thanks to the @registerSchema decorator:

@registerSchema('submission')
class Submission(CommonColumns):
    __tablename__ = 'submission'
    url = Column(String(2000))
    author = Column(String(200))
    author_url = Column(String(2000))
    author_icon = Column(String(2000))
    comment = Column(String(5000))

 

Eve configuration

The DB description is complete. We now need to configure Eve. Eve is configured through a Python dictionary that is shared for the whole application. You can also overload the configuration with a resource specific dictionary.

For the moment, we want to accept new record creation for anyone. We will see how to
turn authentication and permission later.

SETTINGS = {
    'SQLALCHEMY_DATABASE_URI': ('postgresql:///'
    '?host=/tmp/pg_db&dbname=template1'),
    'RESOURCE_METHODS': ['GET', 'POST'],
    'ITEM_METHODS': ['GET'],
    'DOMAIN': {
        'submission': Submission._eve_schema['submission'],
    },
}

 

  • SQLALCHEMY_DATABASE_URL is the address of our PostgreSQL instance. to keep thing simple, we use a local socket.
  • RESOURCE_METHODS and ITEM_METHODS: since permission won’t be enabled yet, we should only accept new items creation which we cover with the POST request. We also accept GET for the moment in order to expose the content of the server DB, this way it will be easier to understand what’s going on. These configuration keys, like the others are covered by the Eve documentation.

Application creation

We will now initialize our Eve object and configure it to use the SQLAlchemy engine.

application = Eve(auth=None, settings=SETTINGS, data=SQL)

# bind SQLAlchemy
db = application.data.driver
Base.metadata.bind = db.engine
db.Model = Base
db.create_all()
if __name__ == "__main__":
    application.run(debug=True)

 

Data structure validation

As we said previously, Python-Eve was historically backed by MongoDB. MongoDB is a no-SQL database with no constraint. That’s why Eve allow the use of an extra configuration to validate the format of the resource. This is the purpose of the

validator
  as an extra argument.
This
validator
  is an object that will validate the dataset integrity from the application level using Cerberus. This topic is also covered by the validation page in the documentation.

You can pass the ValidorSQL object when you initialize the application object.

application = Eve(auth=None, settings=SETTINGS, validator=ValidatorSQL, data=SQL)

It’s still a good idea to use database level constraint to ensure the integrity of the data and as a bonus point, Eve-SQLAlchemy is able to understand some of them and use them to initialize ValidatorSQL default value.

boilerplate

Our application is mostly ready, we need to do the proper

import
  calls.
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.ext.declarative import declarative_base

# Eve imports
from eve import Eve
from eve_sqlalchemy import SQL
from eve_sqlalchemy.validation import ValidatorSQL

# Eve-SQLAlchemy imports
from eve_sqlalchemy.decorators import registerSchema

 

Rock’n roll

For now, we use a user instance of PostgreSQL to run our application. This can easily be done with PostgreSQL with the following calls:

# Purge any existing DB directory
$ rm -rf /tmp/pg_db/
# initialize the local PostgreSQL database store
$ initdb --no-locale --nosync /tmp/pg_db
# Disable the network support, we will only use the local socket
$ echo "listen_addresses = ''" >> /tmp/pg_db/postgresql.conf
# Finally start the postgre process in the foreground
$ postgres -F -k /tmp/pg_db -D /tmp/pg_db

 

We can now run our server:

$ python wsgi.py

 

Our server is now up and running, we can access it on http://127.0.0.1:5000 and browse the nice home interface generated by Python-Eve.

Our first REST call

$ curl -H 'Content-Type: application/json' -vvv -X POST -d '{"url":"http://somewhere/article1","author":"Paul Emiste", "author_url":"http://somewhere-else","author_icon":"http://the_vilain/avatar-13.jpg","comment":"an hateful comment here."}' http://127.0.0.1:5000/submission

We can view this first post in the submission item list at http://127.0.0.1:5000/submission or directly at http://127.0.0.1:5000/submission/1. Here again, Python-Eve do all the work for us.

submission

OpenShift

At this point, our RESTful service is ready to go live and accept public submission. Let’s use a PaaS service to publish it on Internet. Let’s pick one at random and use Openshift.

Let’s adjust the code

First, our little application depend on Eve-SQLAlchemy and Eve. requirements.txt is used by the Python component to declare the external dependencies, let’s just specify that we use it, this way the user will just have to run

pip install -r requirements.txt
  to deploy the application dependencies:
echo Eve-SQLAlchemy > requirements.txt

 

To be able to use OpenShift, we just need to point the URI to the PostgreSQL instance. OpenShift exports some environment variables to describe the location of the different services. We just have to reuse them.

pg_url = 'postgresql:///?host=/tmp/pg_db&dbname=template1'
if 'OPENSHIFT_POSTGRESQL_DB_HOST' in os.environ:
    pg_url = 'postgresql://%s:%s/%s' % (
        os.environ['OPENSHIFT_POSTGRESQL_DB_HOST'],
        os.environ['OPENSHIFT_POSTGRESQL_DB_PORT'],
        os.environ['OPENSHIFT_APP_NAME'])

 

We now need to use pg_url as the URI to the PostgreSQL database.

Enable the application in OpenShift

First, you’ll need to create an account on the OpenShift website, install the rhc command and run rhc setup.

In this example mydomain is your domain as returned by the rhc domain list command.

$ git init
$ editor wsgi.py
$ git add wsgi.py
$ git commit -m “my very first commit”
$ rhc create-app bobby python-3.3 postgresql-9.2
(...)
Your application 'bobby' is now available.
URL: http://bobby-mydomain.rhcloud.com/
SSH to: 552643edfcf933d464000135@bobby-mydomain.rhcloud.com
Git remote: ssh://blablabla@bobby-mydomain.rhcloud.com/~/git/bobby.git/
Cloned to: /home/goneri/bobby
$ git push ssh://blablabla@bobby-mydomain.rhcloud.com/~/git/bobby.git/ master:master -f

 

Here bobby is the name of our application and mydomain, our domain name. Your website should be able on the http://bobby-mydomain.rhcloud.com URL. If it’s not the case, you can call

rhc tail bobby
  to watch the application logs.

Here it is, you can now access your API directly through: http://bobby-mydomain.rhcloud.com

Full source code

The full source code of this example is available in this Git repository: https://github.com/goneri/trollhunter

Conclusion

This shows how, in a few simple steps, you can get a REST API server up and running. It is a simple iteration that allows us to easily implement more of Python-Eve’s large collection of features.


Viewing all articles
Browse latest Browse all 3

Trending Articles