Discussion:
[Twisted-Python] How to design REST API with Twisted?
Wang Yan
2015-10-25 11:04:52 UTC
Permalink
Hi,


I'm confused about how to design REST APIs with Twisted, especially when my app have to interact with MySQL.


Is there any basic design patterns for this kind of situation?


Thanks!
Burak Arslan
2015-10-25 12:13:58 UTC
Permalink
Hey!
Post by Wang Yan
Hi,
I'm confused about how to design REST APIs with Twisted, especially
when my app have to interact with MySQL.
Is there any basic design patterns for this kind of situation?
I do Spyne, and I think it's _fa-bu-lous_ for building any web API on
top of twisted.

It's a bit different from what you to with stock Twisted though. More
specifically, there's no NOT_DONE_YET. The client hangs as long as you
keep returning `Deferred`s. Once you return a non-deferred (and
hopefully something that's compatible with your designated return type)
that object is serialized using the `out_protocol` you pass to your
`Application` and the resulting byte stream is written to the outgoing
stream of your transport of choice. In case of a HTTP-based api, it's
passed to the `transport.write()` function of a `twisted.web.Resource`
instance, along with the outgoing headers that you set.

As for the MySQL part, I use SQLAlchemy exclusively from inside a
function called by deferToThread. Spyne integrates with SQLAlchemy as
well, so you can return directly what SQLA returns, be it objects or rows.

Here's a simple example:
https://github.com/arskom/spyne/blob/master/examples/twisted/resource.py

There's a boilerplate generator here: http://spyne.io/

I hope you find it useful. Any questions, ***@spyne.io is also at
your service.

Best,
Burak
Glyph Lefkowitz
2015-10-26 01:55:06 UTC
Permalink
It's a bit different from what you to with stock Twisted though. More specifically, there's no NOT_DONE_YET.
I should just mention that NOT_DONE_YET actually _predates_ Deferreds, and one glorious day, we will get rid of it :). See for example https://tm.tl/288 <https://tm.tl/288>.

-glyph
Wang Yan
2015-11-04 03:15:16 UTC
Permalink
I'm planning to design some REST APIs with Twisted in Python. For example, I want to use the HTTP method "GET" to fetch a single user's information:

GET http://myhost:8000/api/v1.0/users/[user_id]

I know I should inherit the twisted.web.resource.Resource and implement "getChild" by myself.
The question is, should I implement a class for each segment of the URI? If so, I have to implement class API, class V1, class Users and Class User. In other words, if there're 10 segments in the URI, do I have to implement 10 classes to represent those resources?






At 2015-10-25 20:13:58, "Burak Arslan" <***@arskom.com.tr> wrote:
Hey!


On 10/25/15 13:04, Wang Yan wrote:

Hi,


I'm confused about how to design REST APIs with Twisted, especially when my app have to interact with MySQL.


Is there any basic design patterns for this kind of situation?

I do Spyne, and I think it's fa-bu-lous for building any web API on top of twisted.

It's a bit different from what you to with stock Twisted though. More specifically, there's no NOT_DONE_YET. The client hangs as long as you keep returning `Deferred`s. Once you return a non-deferred (and hopefully something that's compatible with your designated return type) that object is serialized using the `out_protocol` you pass to your `Application` and the resulting byte stream is written to the outgoing stream of your transport of choice. In case of a HTTP-based api, it's passed to the `transport.write()` function of a `twisted.web.Resource` instance, along with the outgoing headers that you set.

As for the MySQL part, I use SQLAlchemy exclusively from inside a function called by deferToThread. Spyne integrates with SQLAlchemy as well, so you can return directly what SQLA returns, be it objects or rows.

Here's a simple example: https://github.com/arskom/spyne/blob/master/examples/twisted/resource.py

There's a boilerplate generator here: http://spyne.io/

I hope you find it useful. Any questions, ***@spyne.io is also at your service.

Best,
Burak
Mashiat Sarker Shakkhar
2015-11-04 04:09:29 UTC
Permalink
Post by Wang Yan
I'm planning to design some REST APIs with Twisted in Python. For
example, I want to use the HTTP method "GET" to fetch a single user's
|GET http://myhost:8000/api/v1.0/users/[user_id] |
I know I should inherit the twisted.web.resource.Resource and
implement "getChild" by myself.
The question is, should I implement a class for each segment of the
URI? If so, I have to implement class API, class V1, class Users and
Class User. In other words, if there're 10 segments in the URI, do I
have to implement 10 classes to represent those resources?
Twisted is too low-level for such use in my opinion. We use Klein
(https://github.com/twisted/klein) which offers nice abstraction above
Twisted.
I know this does not answer your question. Just wanted to make sure that
you are aware of possible options.

-Shakkhar

[...]
Wang Yan
2015-11-05 09:28:10 UTC
Permalink
Thank you to remind me of Klein. I'm very new to Twisted and Klein. What I've known is that Klein is a little like Flask, with which I can implement a UserAPI as follows:

from flask import Flask
from flask.ext.restful import Api, Resource

api = Flask(__name__)
api = Api(app)

class UserAPI(Resource):
def get(self, user_id):
pass

def post(self, user_id):
pass

api.add_resource(UserAPI, '/users/<int:id>', endpoint='user')

Is there any similar usage in Klein?







ÔÚ 2015-11-04 12:09:29£¬"Mashiat Sarker Shakkhar" <***@gmail.com> ÐŽµÀ£º

On 11/3/15 10:15 PM, Wang Yan wrote:


I'm planning to design some REST APIs with Twisted in Python. For example, I want to use the HTTP method "GET" to fetch a single user's information:

GET http://myhost:8000/api/v1.0/users/[user_id]

I know I should inherit the twisted.web.resource.Resource and implement "getChild" by myself.
The question is, should I implement a class for each segment of the URI? If so, I have to implement class API, class V1, class Users and Class User. In other words, if there're 10 segments in the URI, do I have to implement 10 classes to represent those resources?

Twisted is too low-level for such use in my opinion. We use Klein (https://github.com/twisted/klein) which offers nice abstraction above Twisted.
I know this does not answer your question. Just wanted to make sure that you are aware of possible options.

-Shakkhar

[...]
Glyph Lefkowitz
2015-11-05 22:02:53 UTC
Permalink
Post by Wang Yan
from flask import Flask
from flask.ext.restful import Api, Resource
api = Flask(__name__)
api = Api(app)
pass
pass
api.add_resource(UserAPI, '/users/<int:id>', endpoint='user')
Is there any similar usage in Klein?
Yes; in fact this extension for Flask is similar to how twisted.web works internally. I think you're looking for something like this:

from klein import run, route

from twisted.web.resource import Resource

class User(Resource, object):
def __init__(self, user_id):
super(User, self).__init__()
self.user_id = user_id
def render_GET(self, request):
pass
def render_POST(self, request):
pass

@route("/users/<int:user_id>")
def user(request, user_id):
return User(user_id)

run("localhost", 8080)

Loading...