Framework Integration¶
RESTArt looks like a micro-framework. Like many frameworks, RESTArt handles requests and responses in its own way, and you can build REST APIs based on RESTArt without the help of any other framework.
Actually, RESTArt is designed as a library, which is framework-agnostic. It’s the underlying library Werkzeug that gives RESTArt the ability to serve APIs independently. Strictly speaking, RESTArt consists of the framework-agnostic core library and the framework-specific Werkzeug integration.
Why to integrate with other frameworks?¶
With the built-in Werkzeug integration, RESTArt works well for serving standalone APIs. You may ask why we need to integrate RESTArt with other frameworks? The following are the reasons I can think of:
- You are working with an existing or legacy application, which uses a specific framework
- Your API must be based on a useful library or an awesome extension, but it is framework-specific
- The integration with a specific framework can improve the performance of your API (e.g. RESTArt-Falcon)
How to integrate with other frameworks?¶
In RESTArt, framework integration is made easy by using adapters. For a real-world example, see the source code of WerkzeugAdapter
, which is the adapter for the built-in Werkzeug integration.
As another example, We can write an adapter for integrating RESTArt into Flask. Since both RESTArt and Flask are based on Werkzeug, it’s an easy job:
from six import iteritems
from restart.adapter import Adapter, WerkzeugAdapter
from flask import Flask, request
class FlaskAdapter(Adapter):
def __init__(self, *args, **kwargs):
super(FlaskAdapter, self).__init__(*args, **kwargs)
self.werkzeug_adapter = WerkzeugAdapter(*args, **kwargs)
self.app = Flask(__name__)
# Add Flask-specific URI routes
for rule in self.get_embedded_rules():
self.app.add_url_rule(**rule)
def adapt_handler(self, handler, *args, **kwargs):
"""Adapt the request object and the response object for
the `handler` function.
:param handler: the handler function to be adapted.
:param args: a list of positional arguments that will be passed
to the handler.
:param kwargs: a dictionary of keyword arguments that will be passed
to the handler.
"""
return self.werkzeug_adapter.adapt_handler(handler, request,
*args, **kwargs)
def wsgi_app(self, environ, start_response):
"""The actual Flask-specific WSGI application.
See :meth:`~restart.serving.Service.wsgi_app` for the
meanings of the parameters.
"""
return self.app(environ, start_response)
def get_embedded_rules(self):
"""Get the Flask-specific rules used to be embedded into
an existing or legacy application.
Usage:
# The existing Flask application
from flask import Flask
app = Flask()
...
# The RESTArt API
from restart.api import RESTArt
api = RESTArt()
...
# Embed RESTArt into Flask
from restart.serving import Service
from restart.ext.flask.adapter import FlaskAdapter
service = Service(api, FlaskAdapter)
for rule in service.embedded_rules:
app.add_url_rule(**rule)
"""
rules = [
dict(rule=rule.uri, endpoint=endpoint,
view_func=rule.handler, methods=rule.methods)
for endpoint, rule in iteritems(self.adapted_rules)
]
return rules
Framework Adapters¶
As a summary, the following list gives the adapters for some frameworks:
Framework | Adapter | Support Type |
---|---|---|
Werkzeug | WerkzeugAdapter | Built-in class |
Flask | FlaskAdapter | Extension class |
Falcon | RESTArt-Falcon | Extension library |
Feel free to contribute adapters for other frameworks.