+ All Categories
Home > Technology > RESTful Web Services with Python - Dynamic Languages conference

RESTful Web Services with Python - Dynamic Languages conference

Date post: 10-May-2015
Category:
Upload: juozas-kaziukenas
View: 19,819 times
Download: 2 times
Share this document with a friend
36
RESTful Web Services with Python Juozas “Joe” Kaziukėnas http://juokaz.com / [email protected] / @juokaz
Transcript
Page 1: RESTful Web Services with Python - Dynamic Languages conference

RESTful Web Services with

Python

Juozas “Joe” Kaziukėnashttp://juokaz.com / [email protected] / @juokaz

Page 2: RESTful Web Services with Python - Dynamic Languages conference

Who is this guy?• Juozas Kaziukėnas,

Lithuanian• You can call me Joe• 3 years in Edinburgh, UK• CEO of Web Species• Occasional open source

developer• Conferences speaker• More info in http://

juokaz.com

• Tweet me @juokaz

Page 3: RESTful Web Services with Python - Dynamic Languages conference

What is a RESTful API?

Page 4: RESTful Web Services with Python - Dynamic Languages conference

What is an API?• Web service is a type of web application• Integrate different apps together• Mashups

• Content is in multiple formats• JSON• XML• HTML?

• Used by other apps mainly• Not necessary

Page 5: RESTful Web Services with Python - Dynamic Languages conference

REST• REpresentational State Transfer• 99% HTTP, 1% conventions/ideas• Stateless• Resources• Name -> URI• http://apple.com/devices/iphone• Hierarchy

• Operations• Not in the URL, but via HTTP terms

• Trivial to cache• Cache-control, Last-Modified, Expires, Etag

Page 6: RESTful Web Services with Python - Dynamic Languages conference

Difference from other web services• XML-RPC• Single url as a front controller • Calling methods on a remote app• Most of the actions are via POST

• SOAP• No comments…

Page 7: RESTful Web Services with Python - Dynamic Languages conference

Difference from web apps• PUT and DELETE HTTP verbs• POST and GET only supported by browsers today• Create: POST• Update: PUT• Delete: DELETE• View: GET

• Status codes• Not just 404 and 500• Meaning of the response without analyzing the returned

data

• And many other headers• Web page is not a resource, it’s a representation

of a resource

Page 8: RESTful Web Services with Python - Dynamic Languages conference

Accept header means the format

$ curl -H "Accept: application/html" localhost/products/iphone<html><body>Iphone 5</body></html>

$ curl -H "Accept: application/xml" localhost/products/iphone<name>Iphone 5</name>

$ curl -H "Accept: application/json“ localhost/products/iphone{‘name’:‘Iphone 5’}

$ curl -H "Accept: text/plain" localhost/products/iphoneIphone 5

Page 9: RESTful Web Services with Python - Dynamic Languages conference

Doing it wrong

Page 10: RESTful Web Services with Python - Dynamic Languages conference

URLs• Before we had:

http://www.example.com/videos.py?by=joe&type=funny• Now we have:

http://www.example.com/videos/funny/joe/offset/0/10• This is wrong

Page 11: RESTful Web Services with Python - Dynamic Languages conference

REST + XML-RPC• What is new?

http://www.example.com/clients/new• Unclear hierarchy

http://www.example.com/clients/photos/32723• Filtering

http://www.example.com/clients/name/john/offset/10/sort/name

Page 12: RESTful Web Services with Python - Dynamic Languages conference

Wrong• Everything is REST now• But it’s not

• Twitter, Facebook, Google all inventing their own @$^&$s

• “Users are stupid”, ditching standards• How to figure out the URIs?• To fix this you need…

Page 13: RESTful Web Services with Python - Dynamic Languages conference

HATEOASHypermedia as the Engine of Application State

Page 14: RESTful Web Services with Python - Dynamic Languages conference

The steps to being REST• “The Swamp of POX.” You’re using HTTP to make

RPC calls. HTTP is only really used as a tunnel.• Resources. Rather than making every call to a

service endpoint, you have multiple endpoints that are used to represent resources, and you’re talking to them. This is the very beginnings of supporting REST.

• HTTP Verbs. This is the level that something like Rails gives you out of the box: You interact with these Resources using HTTP verbs, rather than always using POST.

• Hypermedia Controls. HATEOAS. You’re 100% REST compliant.

From Richardson Maturity Model

Page 15: RESTful Web Services with Python - Dynamic Languages conference

HATEOAS• A requirement for REST• One url, everything else is discoverable• What to• Do next?• Do with the resource?

• Reduces code errors• Invalid URLS• Invalid state transfers

• Documentation is not needed• Evolution

Page 16: RESTful Web Services with Python - Dynamic Languages conference

XML example

<appointment> <slot id="1234" doctor="mjones" start="1400" end="1450“/> <patient id="jsmith“/> <link rel="cancel" uri="/slots/1234/appointment"/> <link rel="addTest" uri="/slots/1234/appointment/tests"/> <link rel="updateContactInfo" uri="/patients/jsmith/contactInfo"/></appointment>

Page 17: RESTful Web Services with Python - Dynamic Languages conference

Accept header means the format• Media type• Versioning

$ curl -H "Accept: application/vnd.demo.v1+json“ localhost/products/iphone

{‘name’:‘Iphone 5’}

$ curl -H "Accept: application/vnd.demo.v2+json" localhost/products/iphone

{‘product_name’:‘Iphone 5’}

Page 18: RESTful Web Services with Python - Dynamic Languages conference

Solving the problems with Python

Page 19: RESTful Web Services with Python - Dynamic Languages conference

How to create a REST protocol• What are the URIs?• What's the format?• What methods are supported at each URI?• What status codes could be returned?

By Joe Gregorio

Page 20: RESTful Web Services with Python - Dynamic Languages conference

Why Python?• Fast, relatively • Robust to develop• New code live in seconds

• Huge selection of web frameworks• Interfaces with databases, servers etc.• APIs do not need much else

Page 21: RESTful Web Services with Python - Dynamic Languages conference

Python• As long as it’s WSGI it’s OK• Simple code• Different feature sets• Talking here about• Django• Bottle, similar to Flask• Web.py• Tornado (asynchronous)

• Render content in the request format

Page 22: RESTful Web Services with Python - Dynamic Languages conference

Sample API with Djangoxml_poll_resource = Collection( queryset = Poll.objects.all(), permitted_methods = ('GET', 'POST', 'PUT', 'DELETE'), expose_fields = ('id', 'question', 'pub_date'), responder = XMLResponder(paginate_by = 10) ) xml_choice_resource = Collection( queryset = Choice.objects.all(), permitted_methods = ('GET',), expose_fields = ('id', 'poll_id', 'choice'), responder = XMLResponder(paginate_by = 5) )

urlpatterns = patterns('', url(r'^xml/polls/(.*?)/?$', xml_poll_resource), url(r'^xml/choices/(.*?)/?$', xml_choice_resource) )

Page 23: RESTful Web Services with Python - Dynamic Languages conference

Sample API with Bottleimport bottle from bottle import route, run

@route('/', method='GET') def homepage():

return 'Hello world!'

@route('/events/:id', method='GET') def get_event(id):

return dict(name = 'Event ' + str(id))

bottle.debug(True) run()

Page 24: RESTful Web Services with Python - Dynamic Languages conference

Sample API with Tornadoclass PlaceHandler(tornado.web.RequestHandler):    def get(self, id):        self.write('GETting something')     def post(self):        self.write('POSTing something')

application = tornado.web.Application([    (r"/place", PlaceHandler),    (r"/place/([0-9]+)", PlaceHandler)]) if __name__ == "__main__":    http_server = tornado.httpserver.HTTPServer(application)    tornado.ioloop.IOLoop.instance().start()

Page 25: RESTful Web Services with Python - Dynamic Languages conference

MIME types• Detect which format to use from Accept header• Content negotiation

• Mimeparse - http://code.google.com/p/mimeparse/• Use it, works great

> mimeparse:best_match(["application/xbel+xml", "text/xml"], "text/*;q=0.5,*/*; q=0.1").> "text/xml"

Page 26: RESTful Web Services with Python - Dynamic Languages conference

Mimerenderrender_xml = lambda message: '<message>%s</message>'%messagerender_json = lambda **args: json.dumps(args)render_html = lambda message: '<html><body>%s</body></html>'%message

urls = ('/(.*)', 'greet')app = web.application(urls, globals())

class greet:    @mimerender(default = 'html', html = render_html, xml = render_xml, json = render_json)    def GET(self, name):        if not name:             name = 'world'        return {'message': 'Hello, ' + name + '!'}

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

Page 27: RESTful Web Services with Python - Dynamic Languages conference

Return formats• Rendering XML takes a lot of code• doc = xml.dom.minidom.Document()# Something happensreturn doc.toxml()

• JSON is as easy as• json_dumps(data, sort_keys=True)• Maybe allow human readable output• json_dumps(data, sort_keys=True, indent=4)

• JSON is great for Ajax, if not XML brings huge advantages

Page 28: RESTful Web Services with Python - Dynamic Languages conference

Which framework to choose• Django for existing apps• Different sub-frameworks for REST

• Bottle or similar• Small• Effective• Build your own logic

• Asynchronous Tornado • If API needs to be asynchronous

Page 29: RESTful Web Services with Python - Dynamic Languages conference

What’s missing• Cache headers• Authentication• Different types

• No real REST framework

Page 30: RESTful Web Services with Python - Dynamic Languages conference

Applying it practically for Edinburgh Festivals

Page 31: RESTful Web Services with Python - Dynamic Languages conference

Applying it practically for Edinburgh Festivals• Start at http://api.festivalslab.com• 7 summer festivals• Built in 100% Python• Fast• Very stable• Some bad decisions• Works awesome• More info in the blog

Page 32: RESTful Web Services with Python - Dynamic Languages conference

Structure

Page 33: RESTful Web Services with Python - Dynamic Languages conference

Inside• Whole API – 100 LoC of Python code• Mainly interacting with the ElasticSearch server• Scheduled data imports – main task• Nginx as a reverse proxy• Supervisor to manage the processes

Page 34: RESTful Web Services with Python - Dynamic Languages conference

Conclusion

Page 35: RESTful Web Services with Python - Dynamic Languages conference

Conclusion• REST is awesome• Support different formats• Follow HATEOAS• Try to create as little as possible custom

behaviour• Go with light Python code


Recommended