Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/flosch/simpleapi

A simple API-framework to provide an easy to use, consistent and portable client/server-architecture (standalone and also for django, Flask, AppEngine and all WSGI-compatible implementations like gunicorn).
https://github.com/flosch/simpleapi

Last synced: 17 days ago
JSON representation

A simple API-framework to provide an easy to use, consistent and portable client/server-architecture (standalone and also for django, Flask, AppEngine and all WSGI-compatible implementations like gunicorn).

Awesome Lists containing this project

README

        

.. image:: https://travis-ci.org/flosch/simpleapi.svg?branch=master
:target: https://travis-ci.org/flosch/simpleapi
.. image:: http://img.shields.io/pypi/dm/simpleapi.svg
:target: https://pypi.python.org/pypi/simpleapi
.. image:: http://img.shields.io/pypi/v/simpleapi.svg
:target: https://pypi.python.org/pypi/simpleapi
.. image:: http://img.shields.io/badge/gittip-support%20simpleapi-brightgreen.svg
:target: https://www.gittip.com/flosch/

=========
simpleapi
=========

:dev-version: 0.1
:latest stable: 0.0.9
:author: Florian Schlachter
:website: http://www.florian-schlachter.de
:license: MIT-license / see LICENSE file for more
:mailinglist: subscribe: [email protected]
:documentation: http://simpleapi.readthedocs.org

About
=====

simpleapi is an **easy to use, consistent, transparent and portable** way of
providing an API. It supports **several transport formats** (e. g. json, jsonp,
xml, yaml) and provides **server** (standalone and also django, Flask, Google AppEngine and any WSGI-compatible implementation like gunicorn) and **client libraries** (PHP, Python) to interact seamlessly. You can also use nearly every **Ajax framework** (e. g. jQuery, ExtJS, etc.) to access the API.

* server support for **django**, **Flask** and **Google AppEngine**
* client support for **python**, **php** and **javascript**
* dynamic key authentication / ip restriction
* type-conversion / constraints
* object serialization of django model instances, django queryset instances,
mongoengine documents, mongoengine queryset instances
* inheritance / multiple versions of one API
* several encoding/decoding formats (json, jsonp, xml, yaml, etc.)
* several result formats (ie. for ExtJS forms, etc.)
* features: caching, throttling
* debugging and profiling capabilities
* examples

Installation
============

::

pip install --upgrade simpleapi

From GitHub
-----------

::

git clone git://github.com/flosch/simpleapi.git

Dependencies
============

* **server**: django >= 1.1.1, Flask >= 0.1 or Google AppEngine
* Python 2.5 or greater
* simplejson (if you're using Python <= 2.5)
* python-dateutil
* pyyaml (optional, for YAML-support)
* sphinx (optional, for the docs)

(see requirements.txt as well)

Examples
========

SMS-System
----------

Server (handler.py)::

from simpleapi import Namespace, serialize
from models import SMS, APIUser

class SMSAPI(Namespace):
__authentication__ = lambda namespace, access_key: \
APIUser.objects.filter(access_key=access_key).count() > 0

def send(self, to, msg, from='testsender'):
sms = SMS.objects.create(
to=to
msg=msg,
from=from
)
return {
'sent': sms.send(),
'obj': serialize(sms, excludes=[re.compile('^date'),])
}
send.published = True
send.constraints = {'to': re.compile(r'^\+\d{2,}\ \d{3,}\ \d{5,}')}

def status(self, id):
return SMS.objects.get(id=id)
status.published = True
status.constraints = {'id': int}

def last(self, numbers=5):
return SMS.objects.all()[:numbers]
last.published = True
last.constraints = {'numbers': int}

**Standalone-Server** (app.py)::

from simpleapi import Route
from handlers import SMSAPI

route = Route(SMSAPI, framework='standalone', path=r'^/api/')
route.serve() # serves on port 5050 by default

Gunicorn (**WSGI-compatible implementation**) (app.py)::

from simpleapi import Route
from handlers import SMSAPI

route = Route(SMSAPI, framework='wsgi', path=r'^/api/')

# start Gunicorn (with 5 workers):
# gunicorn -w 5 app:route

**Django-Server** (urls.py)::

from handlers import SMSAPI
urlpatterns = patterns('',
(r'^api/$', Route(SMSAPI))
)

**Flask-Server** (app.py)::

from flask import Flask
from simpleapi import Route
from handlers import SMSAPI

app = Flask(__name__)
app.route('/api/')(Route(SMSAPI, framework='flask'))

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

**Google AppEngine** (main.py)::

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

from simpleapi import Route
from handlers import SMSAPI

def main():
application = webapp.WSGIApplication(
[('/api/', Route(SMSAPI, framework='appengine'))]
)
util.run_wsgi_app(application)

if __name__ == '__main__':
main()

Client (python/**remote**)::

from simpleapi import Client

client = Client(ns='http://remote.tld:8888/api/', access_key='mysecret',
transport_type='xml')

sms = client.sms(to='555123', msg='Hey yo! This is simpleapi calling.')
print "Sent successful?", sms['sent']

sms = client.sms(to='555123', msg='2nd test with own sender',
sender='simpleapi')
print "Sent successful?", sms['sent']
print "Which sender?", sms['obj']['sender']

Client (python/**local**)::

from simpleapi import DummyClient, Route
from handlers import SMSAPI

client = DummyClient(Route(SMSAPI, framework='dummy'),
access_key='mysecret')

sms = client.sms(to='555123', msg='Hey yo! This is simpleapi calling.')
print "Sent successful?", sms['sent']

sms = client.sms(to='555123', msg='2nd test with own sender',
sender='simpleapi')
print "Sent successful?", sms['sent']
print "Which sender?", sms['obj']['sender']

Client (PHP)::

require_once("class.client.php");

$client = new Client($ns="http://localhost:8888/api/",
$access_key='mysecret');
print("Sent? ".$client->sms(array(
'to' => '555123',
'msg' => 'Hey yo! This is the PHP client sending you a SMS.'
))->{'sent'});

Client (jQuery)::

jQuery.get(
"/api/",
{_call: 'send', to: '555123', 'msg': 'Hey ya!'},
function (return) {
if (return.result.sent)
alert('Sent successfully!');
else
alert('Sending failed!');
}
)

Calculator
----------

Server (handler.py)::

from simpleapi import Namespace

class CalculatorAPI(Namespace):
__ip_restriction__ = ['127.0.0.*',]
__authentication__ = "lets_calc"

def power(self, a, b):
return a ** b
power.published = True
power.constraints = lambda namespace, key, value: float(value)

def sum(self, **kwargs)
return sum(kwargs.values())
sum.published = True
sum.constraints = lambda namespace, key, value: float(value)

**Standalone-Server** (app.py)::

from simpleapi import Route
from handlers import CalculatorAPI

route = Route(CalculatorAPI, framework='standalone', path=r'^/api/')
route.serve() # serves on port 5050 by default

Gunicorn (**WSGI-compatible implementation**) (app.py)::

from simpleapi import Route
from handlers import CalculatorAPI

route = Route(CalculatorAPI, framework='wsgi', path=r'^/api/')

# start Gunicorn (with 5 workers):
# gunicorn -w 5 app:route

**Django-Server** (urls.py)::

from handlers import CalculatorAPI
urlpatterns = patterns('',
(r'^api/$', Route(CalculatorAPI))
)

**Flask-Server** (app.py)::

from flask import Flask
from simpleapi import Route
from handlers import CalculatorAPI

app = Flask(__name__)
app.route('/api/')(Route(CalculatorAPI, framework='flask'))

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

**Google AppEngine** (main.py)::

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

from simpleapi import Route
from handlers import CalculatorAPI

def main():
application = webapp.WSGIApplication(
[('/api/', Route(CalculatorAPI, framework='appengine'))]
)
util.run_wsgi_app(application)

if __name__ == '__main__':
main()

Client (python/**remote**)::

from simpleapi import Client

client = Client(ns='http://remote.tld:8888/api/', access_key='lets_calc')

print "5 ** 8 =", client.power(a=5, b=8)
print "1+2+3+4+5+6+7 =", client.sum(a=1, b=2, c=3, d=4, e=5, f=6, g=7)

Client (python/**local**)::

from simpleapi import DummyClient, Route
from handlers import CalculatorAPI

client = DummyClient(Route(CalculatorAPI, framework='dummy'),
access_key='lets_calc')

print "5 ** 8 =", client.power(a=5, b=8)
print "1+2+3+4+5+6+7 =", client.sum(a=1, b=2, c=3, d=4, e=5, f=6, g=7)

Client (PHP)::

require_once("class.client.php");

$client = new Client($ns="http://localhost:8888/api/",
$access_key='lets_calc');
print("5 ** 8 = ".$client->power(array('a'=>5, 'b'=>8)));

Client (jQuery)::

jQuery.get(
"/api/",
{_call: 'power', a: 5, b: 8, _access_key: "lets_calc"},
function (return) {
alert('5 ** 8 = ' + return.result)
}
)