Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
REST with Sinatra  Emanuele DelBono      @emadb
Thanks to the sponsors
About meI’m a software developer inCodicePlastico.I write Web applications in C# withASP.NET MVC. I’m a member of<WEBdeBS/...
Agenda‣ Philosophy. Sweet and easy.‣ REST. Yet another boring introduction.‣ Hello world. Show some magic.‣ Features. Amaz...
Sinatra as a REST server
What is isn’t‣ Sinatra is not -another MV* framework -a full framework like Rails -an ORM -a game project
Sinatra is just a DSL   written in ruby
Hello world
Hello world~$ gem install sinatra~$ vi app.rb
Hello world~$ gem install sinatra~$ vi app.rbrequire sinatraget / do hello world!end
Hello world~$ gem install sinatra~$ vi app.rbrequire sinatraget / do hello world!end~$ ruby app.rb
Is it really so easy?‣ Yep! (special thanks to Ruby  sweeties)  - get is a just a method (more later)  - the route is the ...
Let’s go RESTWhat? Yet another REST introduction?
5 REST principles‣ Uniform Interface    ‣ HATEAOS‣   Stateless‣   Cacheable‣   Client-Server‣   Layered System
Sinatra and REST‣ Sinatra supports  - All HTTP verbs  - Caching  - Content types  - Routes  - ....and all you need to buil...
Give a look at the
Verbs‣ Support for all verbs  - Get, Post, Put, Delete, Head, Options,    Patch‣ They are just methods
Routing‣ No need of route files or route  maps‣ The verb method takes the route  as parameter
Routingget ( ‘/todos’ ) {...}get ( ‘/todo/:id’ ) {...}get ( ‘/*’ ) {...}
Routing Conditionsget /foo, :agent => /Mozilla/(d.d)sw?/ do "Youre using Mozilla version#{params[:agent][0]}"endget /foo d...
Routing Customset(:prob) { |v| condition { rand <= v } }get /win_a_car, :prob => 0.1 do "You won!"endget /win_a_car {"Sorr...
Xml or Json‣ You can set the content_type to  whatever you needcontent_type :jsoncontent_type :xml
Status codes‣ Set the HTTP status code is  status 200  status 403
Http Headers‣ You can add your own headersheaders "X-My-Value" => "this is myheader"
Redirectredirect to ‘/todos’
Cache‣ You can set your cache information  using the headers methodheaders "Cache-Control" => "public,must-revalidate, max...
Cache‣ Or better, you can use the expiresexpires 3600, :public
Filtersbefore do #...endafter do #...
Authentication‣ Basic authentication support through  Rack‣ Key-based authentication
Basic Authenticationuse Rack::Auth::Basic, "Private area" do|usr, pwd| [usr, pwd] == [admin, admin]end
Token authenticationbefore do if env[‘HTTP_MY_KEY’] ==’rubyrocks‘   error 401 endend
Demo
Stream‣ Supports streamed content‣ Streamed responses have no Content-  Length header‣ But have Transfer-Encoding: chunked
Inside
Inside‣ Sinatra source code is on github:    http://github.com/sinatra/sinatra‣ Less than 2k lines of code‣ Based on Rack
Application styleClassic application         vsModular application
Classic App  Single file Standalone
Modular Apps         Multi fileSubclassing Sinatra::Base  Distributed as library
The codeWhat happen when a request arrives?get (‘/hello’) do { ‘hello world’ }
Where do get come from?require "sinatra"outer_self = selfget / do "outer self: #{outer_self}, inner self: #{self}"end oute...
$ irb
$ irbruby-1.9.2-p180 > require sinatra
$ irbruby-1.9.2-p180 > require sinatra=> true
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>rub...
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>rub...
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>rub...
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>rub...
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>rub...
$ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>rub...
Where do get come from?‣ get is defined twice:  – Once in Sinatra::Delegator a mixin    extending Object  – Once in Sinatra...
How the block is invoked?‣ The route! method finds the correct  routedef route_eval throw :halt, yieldend‣ throw is used to...
In base.rb‣ The invokerdef invoke res = catch(:halt) { yield } # .... other code...end
It’s a kind of magic!
Sinatra has ended his set    (crowd applauds)
Questions?
demos at:http://github.com/emadb/     webnetconf_demo
Please rate this sessionScan the code, go online, rate this session
Sinatra for REST services
Sinatra for REST services
Sinatra for REST services
Upcoming SlideShare
Loading in …5
×

Sinatra for REST services

12,163 views

Published on

Introduction to Sinatra miniframework. This talk was given at the @Webnetconf in Milan 2012.

Published in: Technology
  • Be the first to comment

Sinatra for REST services

  1. 1. REST with Sinatra Emanuele DelBono @emadb
  2. 2. Thanks to the sponsors
  3. 3. About meI’m a software developer inCodicePlastico.I write Web applications in C# withASP.NET MVC. I’m a member of<WEBdeBS/> a local webcommunity....and I’m a wannabe Rubydeveloper ;-)
  4. 4. Agenda‣ Philosophy. Sweet and easy.‣ REST. Yet another boring introduction.‣ Hello world. Show some magic.‣ Features. Amazing!‣ Inside. How it works?‣ Q&A. ...and thanks.
  5. 5. Sinatra as a REST server
  6. 6. What is isn’t‣ Sinatra is not -another MV* framework -a full framework like Rails -an ORM -a game project
  7. 7. Sinatra is just a DSL written in ruby
  8. 8. Hello world
  9. 9. Hello world~$ gem install sinatra~$ vi app.rb
  10. 10. Hello world~$ gem install sinatra~$ vi app.rbrequire sinatraget / do hello world!end
  11. 11. Hello world~$ gem install sinatra~$ vi app.rbrequire sinatraget / do hello world!end~$ ruby app.rb
  12. 12. Is it really so easy?‣ Yep! (special thanks to Ruby sweeties) - get is a just a method (more later) - the route is the parameter - the block is what should be executed - the block returns the result - the server is built in (based on Rack)
  13. 13. Let’s go RESTWhat? Yet another REST introduction?
  14. 14. 5 REST principles‣ Uniform Interface ‣ HATEAOS‣ Stateless‣ Cacheable‣ Client-Server‣ Layered System
  15. 15. Sinatra and REST‣ Sinatra supports - All HTTP verbs - Caching - Content types - Routes - ....and all you need to build a rest server
  16. 16. Give a look at the
  17. 17. Verbs‣ Support for all verbs - Get, Post, Put, Delete, Head, Options, Patch‣ They are just methods
  18. 18. Routing‣ No need of route files or route maps‣ The verb method takes the route as parameter
  19. 19. Routingget ( ‘/todos’ ) {...}get ( ‘/todo/:id’ ) {...}get ( ‘/*’ ) {...}
  20. 20. Routing Conditionsget /foo, :agent => /Mozilla/(d.d)sw?/ do "Youre using Mozilla version#{params[:agent][0]}"endget /foo do # Matches non-Mozilla browsersend
  21. 21. Routing Customset(:prob) { |v| condition { rand <= v } }get /win_a_car, :prob => 0.1 do "You won!"endget /win_a_car {"Sorry, you lost."}
  22. 22. Xml or Json‣ You can set the content_type to whatever you needcontent_type :jsoncontent_type :xml
  23. 23. Status codes‣ Set the HTTP status code is status 200 status 403
  24. 24. Http Headers‣ You can add your own headersheaders "X-My-Value" => "this is myheader"
  25. 25. Redirectredirect to ‘/todos’
  26. 26. Cache‣ You can set your cache information using the headers methodheaders "Cache-Control" => "public,must-revalidate, max-age=3600","Expires" => Time.at(Time.now.to_i + (60
  27. 27. Cache‣ Or better, you can use the expiresexpires 3600, :public
  28. 28. Filtersbefore do #...endafter do #...
  29. 29. Authentication‣ Basic authentication support through Rack‣ Key-based authentication
  30. 30. Basic Authenticationuse Rack::Auth::Basic, "Private area" do|usr, pwd| [usr, pwd] == [admin, admin]end
  31. 31. Token authenticationbefore do if env[‘HTTP_MY_KEY’] ==’rubyrocks‘ error 401 endend
  32. 32. Demo
  33. 33. Stream‣ Supports streamed content‣ Streamed responses have no Content- Length header‣ But have Transfer-Encoding: chunked
  34. 34. Inside
  35. 35. Inside‣ Sinatra source code is on github: http://github.com/sinatra/sinatra‣ Less than 2k lines of code‣ Based on Rack
  36. 36. Application styleClassic application vsModular application
  37. 37. Classic App Single file Standalone
  38. 38. Modular Apps Multi fileSubclassing Sinatra::Base Distributed as library
  39. 39. The codeWhat happen when a request arrives?get (‘/hello’) do { ‘hello world’ }
  40. 40. Where do get come from?require "sinatra"outer_self = selfget / do "outer self: #{outer_self}, inner self: #{self}"end outer self: main, inner self: #<Sinatra::Application: closures in ruby are “scope gate”
  41. 41. $ irb
  42. 42. $ irbruby-1.9.2-p180 > require sinatra
  43. 43. $ irbruby-1.9.2-p180 > require sinatra=> true
  44. 44. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)
  45. 45. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>
  46. 46. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)
  47. 47. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]
  48. 48. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target
  49. 49. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target=> Sinatra::Application
  50. 50. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target=> Sinatra::Applicationruby-1.9.2-p180 > Sinatra::Application.method(:get)
  51. 51. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target=> Sinatra::Applicationruby-1.9.2-p180 > Sinatra::Application.method(:get)=> #<Method:Sinatra::Application(Sinatra::Base).get>
  52. 52. Where do get come from?‣ get is defined twice: – Once in Sinatra::Delegator a mixin extending Object – Once in Sinatra::Application‣ The Delegator implementation simply delegate to Application‣ That’s why we have get/post/... methods on main
  53. 53. How the block is invoked?‣ The route! method finds the correct routedef route_eval throw :halt, yieldend‣ throw is used to go back to the invoker
  54. 54. In base.rb‣ The invokerdef invoke res = catch(:halt) { yield } # .... other code...end
  55. 55. It’s a kind of magic!
  56. 56. Sinatra has ended his set (crowd applauds)
  57. 57. Questions?
  58. 58. demos at:http://github.com/emadb/ webnetconf_demo
  59. 59. Please rate this sessionScan the code, go online, rate this session

×