Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

Sinatra for REST services

  1. REST with Sinatra Emanuele DelBono @emadb
  2. Thanks to the sponsors
  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. 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. Sinatra as a REST server
  6. What is isn’t ‣ Sinatra is not -another MV* framework -a full framework like Rails -an ORM -a game project
  7. Sinatra is just a DSL written in ruby
  8. Hello world
  9. Hello world ~$ gem install sinatra ~$ vi app.rb
  10. Hello world ~$ gem install sinatra ~$ vi app.rb require 'sinatra' get '/' do 'hello world!' end
  11. Hello world ~$ gem install sinatra ~$ vi app.rb require 'sinatra' get '/' do 'hello world!' end ~$ ruby app.rb
  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. Let’s go REST What? Yet another REST introduction?
  14. 5 REST principles ‣ Uniform Interface ‣ HATEAOS ‣ Stateless ‣ Cacheable ‣ Client-Server ‣ Layered System
  15. Sinatra and REST ‣ Sinatra supports - All HTTP verbs - Caching - Content types - Routes - ....and all you need to build a rest server
  16. Give a look at the
  17. Verbs ‣ Support for all verbs - Get, Post, Put, Delete, Head, Options, Patch ‣ They are just methods
  18. Routing ‣ No need of route files or route maps ‣ The verb method takes the route as parameter
  19. Routing get ( ‘/todos’ ) {...} get ( ‘/todo/:id’ ) {...} get ( ‘/*’ ) {...}
  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. 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. Xml or Json ‣ You can set the content_type to whatever you need content_type :json content_type :xml
  23. Status codes ‣ Set the HTTP status code is status 200 status 403
  24. Http Headers ‣ You can add your own headers headers "X-My-Value" => "this is my header"
  25. Redirect redirect to ‘/todos’
  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. Cache ‣ Or better, you can use the expires expires 3600, :public
  28. Filters before do #... end after do #...
  29. Authentication ‣ Basic authentication support through Rack ‣ Key-based authentication
  30. Basic Authentication use Rack::Auth::Basic, "Private area" do |usr, pwd| [usr, pwd] == ['admin', 'admin'] end
  31. Token authentication before do if env[‘HTTP_MY_KEY’] ==’rubyrocks‘ error 401 end end
  32. Demo
  33. Stream ‣ Supports streamed content ‣ Streamed responses have no Content- Length header ‣ But have Transfer-Encoding: chunked
  34. Inside
  35. Inside ‣ Sinatra source code is on github: http://github.com/sinatra/sinatra ‣ Less than 2k lines of code ‣ Based on Rack
  36. Application style Classic application vs Modular application
  37. Classic App Single file Standalone
  38. Modular Apps Multi file Subclassing Sinatra::Base Distributed as library
  39. The code What happen when a request arrives? get (‘/hello’) do { ‘hello world’ }
  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. $ irb
  42. $ irb ruby-1.9.2-p180 > require 'sinatra'
  43. $ irb ruby-1.9.2-p180 > require 'sinatra' => true
  44. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-1.9.2-p180 > method(:get)
  45. $ irb ruby-1.9.2-p180 > require 'sinatra' => true ruby-1.9.2-p180 > method(:get) => #<Method: Object(Sinatra::Delegator)#get>
  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. $ 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. $ 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. $ 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. $ 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. $ 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. 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. 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. In base.rb ‣ The invoker def invoke res = catch(:halt) { yield } # .... other code... end
  55. It’s a kind of magic!
  56. Sinatra has ended his set (crowd applauds)
  57. Questions?
  58. demos at: http://github.com/emadb/ webnetconf_demo
  59. Please rate this session Scan the code, go online, rate this session

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
Advertisement