• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
RESTful Web Services with Python - Confoo

RESTful Web Services with Python - Confoo






Total Views
Views on SlideShare
Embed Views



1 Embed 1

http://www.linkedin.com 1



Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

    RESTful Web Services with Python - Confoo RESTful Web Services with Python - Confoo Presentation Transcript

    • Juozas “Joe” Kaziukėnashttp://juokaz.com / juozas@juokaz.com / @juokaz
    • • 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
    • • 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
    • • 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
    • • XML-RPC • Single url as a front controller • Calling methods on a remote app • Most of the actions are via POST• SOAP • No comments…
    • • 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
    • $ curl -H "Accept: application/html" localhost/products/iphone<html><body>Iphone 5</body></html>$ curl -H "Accept: application/xml" localhost/products/iphone<product><name>Iphone 5</name></product>$ curl -H "Accept: application/json“ localhost/products/iphone{‘name’:‘Iphone 5’}$ curl -H "Accept: text/plain" localhost/products/iphoneIphone 5
    • • 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
    • • What is new?http://www.example.com/clients/new• Unclear hierarchyhttp://www.example.com/clients/photos/32723• Filteringhttp://www.example.com/clients/name/john/offset/10/sort/name
    • • 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…
    • Hypermedia as the Engine of Application State
    • • “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
    • • 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
    • <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>
    • • 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’}
    • • What are the URIs?• Whats the format?• What methods are supported at each URI?• What status codes could be returned? By Joe Gregorio
    • • 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
    • • 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
    • 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^polls/(.*?)/?$, xml_poll_resource), url(r^choices/(.*?)/?$, xml_choice_resource))
    • import bottlefrom 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))run()
    • 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) tornado.ioloop.IOLoop.instance().start()
    • • 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"
    • 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__": app.run()
    • • Rendering XML takes a lot of code • doc = xml.dom.minidom.Document() # Something happens return 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 consumption• XML is better than JSON for anything else
    • • 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
    • • Cache headers• Authentication • Different types• No real REST framework
    • • Start at http://api.festivalslab.com• 7 summer festivals• Built in 100% Python• Fast• Very stable• Some bad decisions• Works really well• More info in the blog
    • • 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
    • • REST is awesome• Support different formats• Follow HATEOAS• Try to create as little as possible custom behavior• Go with light Python code
    • We can help you build them, talk to us!Keep in touch: http://juokaz.com / juozas@juokaz.com / @juokaz