Successfully reported this slideshow.

Sinatra for REST services

14

Share

Upcoming SlideShare
Sinatra Rack And Middleware
Sinatra Rack And Middleware
Loading in …3
×
1 of 62
1 of 62

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Sinatra for REST services

  1. 1. REST with Sinatra Emanuele DelBono @emadb
  2. 2. Thanks to the sponsors
  3. 3. About me I’m a software developer in CodicePlastico. I write Web applications in C# with ASP.NET MVC. I’m a member of <WEBdeBS/> a local web community. ...and I’m a wannabe Ruby developer ;-)
  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.rb require 'sinatra' get '/' do 'hello world!' end
  11. 11. Hello world ~$ gem install sinatra ~$ vi app.rb require 'sinatra' get '/' 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 REST What? 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. Routing get ( ‘/todos’ ) {...} get ( ‘/todo/:id’ ) {...} get ( ‘/*’ ) {...}
  20. 20. Routing Conditions get '/foo', :agent => /Mozilla/(d.d)s w?/ do "You're using Mozilla version #{params[:agent][0]}" end get '/foo' do # Matches non-Mozilla browsers end
  21. 21. Routing Custom set(:prob) { |v| condition { rand <= v } } get '/win_a_car', :prob => 0.1 do "You won!" end get '/win_a_car' {"Sorry, you lost."}
  22. 22. Xml or Json ‣ You can set the content_type to whatever you need content_type :json content_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 headers headers "X-My-Value" => "this is my header"
  25. 25. Redirect redirect to ‘/todos’
  26. 26. Cache ‣ You can set your cache information using the headers method headers "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 expires expires 3600, :public
  28. 28. Filters before do #... end after do #...
  29. 29. Authentication ‣ Basic authentication support through Rack ‣ Key-based authentication
  30. 30. Basic Authentication use Rack::Auth::Basic, "Private area" do |usr, pwd| [usr, pwd] == ['admin', 'admin'] end
  31. 31. Token authentication before do if env[‘HTTP_MY_KEY’] ==’rubyrocks‘ error 401 end end
  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 style Classic application vs Modular application
  37. 37. Classic App Single file Standalone
  38. 38. Modular Apps Multi file Subclassing Sinatra::Base Distributed as library
  39. 39. The code What happen when a request arrives? get (‘/hello’) do { ‘hello world’ }
  40. 40. Where do get come from? require "sinatra" outer_self = self get '/' 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. $ irb ruby-1.9.2-p180 > require 'sinatra'
  43. 43. $ irb ruby-1.9.2-p180 > require 'sinatra' => true
  44. 44. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-1.9.2-p180 > method(:get)
  45. 45. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-1.9.2-p180 > method(:get) => #<Method: Object(Sinatra::Delegator)#get>
  46. 46. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-1.9.2-p180 > method(:get) => #<Method: Object(Sinatra::Delegator)#get> ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)
  47. 47. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-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. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-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. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-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. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-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 ruby-1.9.2-p180 > Sinatra::Application.method(:get)
  51. 51. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-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 ruby-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 route def route_eval throw :halt, yield end ‣ throw is used to go back to the invoker
  54. 54. In base.rb ‣ The invoker def 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 session Scan the code, go online, rate this session

Editor's Notes

  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • ×