Your SlideShare is downloading. ×
RESTful Web Services with Python - Dynamic Languages conference
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

RESTful Web Services with Python - Dynamic Languages conference


Published on

Published in: Technology

  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. ‎RESTful Web Services with Python
    Juozas“Joe”Kaziukėnas / / @juokaz
  • 2. Who is this guy?
    JuozasKaziukė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
    Tweet me @juokaz
  • 3. What is a RESTful API?
  • 4. What is an API?
    Web service is a type of web application
    Integrate different apps together
    Content is in multiple formats
    Used by other apps mainly
    Not necessary
  • 5. REST
    REpresentational State Transfer
    99% HTTP, 1% conventions/ideas
    Name -> URI
    Not in the URL, but via HTTP terms
    Trivial to cache
    Cache-control, Last-Modified, Expires, Etag
  • 6. Difference from other web services
    Single url as a front controller
    Calling methods on a remote app
    Most of the actions are via POST
    No comments…
  • 7. 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
  • 8. 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
  • 9. Doing it wrong
  • 10. URLs
    Before we had:
    Now we have:
    This is wrong
  • 11. REST + XML-RPC
    What is new?
    Unclear hierarchy
  • 12. 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…
  • 13. HATEOAS
    Hypermedia as the Engine of Application State
  • 14. 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
  • 15. 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
  • 16. XML example
    <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"/>
  • 17. Accept header means the format
    Media type
    $ 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’}
  • 18. Solving the problems with Python
  • 19. 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
  • 20. 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
  • 21. Python
    As long as it’s WSGI it’s OK
    Simple code
    Different feature sets
    Talking here about
    Bottle, similar to Flask
    Tornado (asynchronous)
    Render content in the request format
  • 22. Sample API with Django
    xml_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)
  • 23. Sample API with Bottle
    importbottlefrombottleimport route, run
    @route('/', method='GET')
    return'Hello world!'
    @route('/events/:id', method='GET')
    returndict(name = 'Event ' + str(id))
  • 24. Sample API with Tornado
    class 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)
  • 25. MIME types
    Detect which format to use from Accept header
    Content negotiation
    Mimeparse -
    Use it, works great
    > mimeparse:best_match(["application/xbel+xml", "text/xml"], "text/*;q=0.5,*/*; q=0.1").> "text/xml"
  • 26. Mimerender
    render_xml= lambda message: '<message>%s</message>'%messagerender_json = lambda **args: json.dumps(args)render_html = lambda message: '<html><body>%s</body></html>'%messageurls = ('/(.*)', '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__":
  • 27. 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
  • 28. Which framework to choose
    Django for existing apps
    Different sub-frameworks for REST
    Bottle or similar
    Build your own logic
    Asynchronous Tornado
    If API needs to be asynchronous
  • 29. What’s missing
    Cache headers
    Different types
    No real REST framework
  • 30. Applying it practically for Edinburgh Festivals
  • 31. Applying it practically for Edinburgh Festivals
    Start at
    7 summer festivals
    Built in 100% Python
    Very stable
    Some bad decisions
    Works awesome
    More info in the blog
  • 32. Structure
  • 33. 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
  • 34. Conclusion
  • 35. Conclusion
    REST is awesome
    Support different formats
    Follow HATEOAS
    Try to create as little as possible custom behaviour
    Go with light Python code
  • 36. Keep in touch: / / @juokaz
    Thank you!
    We can help you build them, talk to us!