SlideShare a Scribd company logo
1 of 69
Rack Middleware
     David Dollar
What is Rack?
A Rack application is a Ruby object that responds to call.

       It takes exactly one argument, the environment.

         It returns an Array of exactly three values:
            The status, the headers, and the body.

The headers should respond to each and yield key/value pairs.

 The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
lambda do |environment|
  [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ]
end


      A Rack application is a Ruby object that responds to call.

          It takes exactly one argument, the environment.

             It returns an Array of exactly three values:
                The status, the headers, and the body.

   The headers should respond to each and yield key/value pairs.

     The body should respond to each and yield String objects.
Rack and Rails
Before Rails 2.3
Before Rails 2.3

Apache
Before Rails 2.3

Apache     Passenger
Before Rails 2.3

Apache     Passenger        Rails
Before Rails 2.3

Apache     Passenger        Rails




         After Rails 2.3
Before Rails 2.3

Apache     Passenger        Rails




         After Rails 2.3

Apache
Before Rails 2.3

Apache     Passenger        Rails




         After Rails 2.3

Apache     Passenger
Before Rails 2.3

Apache     Passenger        Rails




         After Rails 2.3

Apache     Passenger        Rails
Before Rails 2.3

Apache     Passenger        Rails




         After Rails 2.3

Apache     Passenger        Rails
Passenger   ActionController::Base#call(env)   Rails
What is Rack
Middleware?
Passenger   ActionController::Base#call(env)   Rails
Passenger   Middleware   Rails
Passenger              Middleware                     Rails


 class ExampleMiddleware

   def initialize(next_in_chain)
     @next_in_chain = next_in_chain
   end

   def call(env)
     if env['PATH_INFO'] =~ Regexp.new('^/api')
       [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
     else
       env['mydata'] = 'test'
       @next_in_chain.call(env)
     end
   end

 end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ]
      else
        env['mydata'] = 'test'
        @next_in_chain.call(env)
      end
    end

  end
Example
Existing Middleware
Rack::Cache
http://github.com/rtomayko/rack-cache
App Server   Rack::Cache   Rails



               Storage
App Server   Rack::Cache   Rails



               Storage
Rack::Bug
http://github.com/brynary/rack-bug
Rack::OpenID
http://github.com/josh/rack-openid
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
class SessionsController

  def new
    render :new   # contains a textbox called quot;identityquot;
  end

  def create
    if openid = request.env['rack.openid.response']
      case openid.status
         when :success # ...
         when :failure # ...
      end
    else
      response.headers['WWW-Authenticate'] = Rack::OpenID.build_header(
         :identifier => params[:identity]
      )
      render :text => '', :status => 401
    end
  end

end
Rack::Debug
http://github.com/ddollar/rack-debug
# app/controllers/users_controller.rb
@user = User.find(params[:id])
debugger
render :show



# run the rake task,
$ rake debug
Connected.



# refresh a page in your browser, your app will break at debugger statements
(rdb:1) p @user
<User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
# app/controllers/users_controller.rb
@user = User.find(params[:id])
debugger
render :show



# run the rake task
$ rake debug
Connected.
(rdb:1) p @user
<User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
# app/controllers/users_controller.rb
@user = User.find(params[:id])
debugger
render :show



# run the rake task
$ rake debug
Connected.
(rdb:1) p @user
<User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
# app/controllers/users_controller.rb
@user = User.find(params[:id])
debugger
render :show



# run the rake task
$ rake debug
Connected.
(rdb:1) p @user
<User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
Using Middleware
Passenger              Middleware                     Rails

  class ExampleMiddleware

    def initialize(next_in_chain)
      @next_in_chain = next_in_chain
    end

    def call(env)
      if env['PATH_INFO'] =~ Regexp.new('^/api')
        [ 200, { 'Content-Type' => 'text/xml' }, '<?xml?>' ]
      else
        @next_in_chain.call(env)
      end
    end

  end
Passenger            Middleware                     Rails



        class ExampleMiddleware
          # ...
        end



        # config/environment.rb
        config.middleware.use 'ExampleMiddleware'
Passenger            Middleware                     Rails



        class ExampleMiddleware
          # ...
        end



        # config/environment.rb
        config.middleware.use 'ExampleMiddleware'
Passenger            Middleware      Sinatra



        class ExampleMiddleware
          # ...
        end



        app = Rack::Builder.new do
          use ExampleMiddleware
          run MySinatraApp.new
        end
Passenger            Middleware      Sinatra



        class ExampleMiddleware
          # ...
        end



        app = Rack::Builder.new do
          use ExampleMiddleware
          run MySinatraApp.new
        end
Passenger            Middleware      Sinatra



        class ExampleMiddleware
          # ...
        end



        app = Rack::Builder.new do
          use ExampleMiddleware
          run MySinatraApp.new
        end
class ExampleMiddleware
  # ...
end



# Rails
config.middleware.use 'ExampleMiddleware'



# Rack::Builder
app = Rack::Builder.new do
  use ExampleMiddleware
  run MySinatraApp.new
end
class ExampleMiddleware
  # ...
end



# Rails
config.middleware.use 'ExampleMiddleware'
config.middleware.use 'ExampleMiddlewareTwo'



# Rack::Builder
app = Rack::Builder.new do
  use ExampleMiddleware
  use ExampleMiddlewareTwo
  run MySinatraApp.new
end
class ExampleMiddleware
  # ...
end



# Rails
config.middleware.use 'ExampleMiddleware'
config.middleware.use 'ExampleMiddlewareTwo'
config.middleware.use 'ExampleMiddlewareThree'



# Rack::Builder
app = Rack::Builder.new do
  use ExampleMiddleware
  use ExampleMiddlewareTwo
  use ExampleMiddlewareThree
  run MySinatraApp.new
end
Questions?

More Related Content

What's hot

Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl TechniquesDave Cross
 
Introduction to Perl - Day 2
Introduction to Perl - Day 2Introduction to Perl - Day 2
Introduction to Perl - Day 2Dave Cross
 
Bioinformatics p1-perl-introduction v2013
Bioinformatics p1-perl-introduction v2013Bioinformatics p1-perl-introduction v2013
Bioinformatics p1-perl-introduction v2013Prof. Wim Van Criekinge
 
Perl programming language
Perl programming languagePerl programming language
Perl programming languageElie Obeid
 
LPW: Beginners Perl
LPW: Beginners PerlLPW: Beginners Perl
LPW: Beginners PerlDave Cross
 
Actor Clustering with Docker Containers and Akka.Net in F#
Actor Clustering with Docker Containers and Akka.Net in F#Actor Clustering with Docker Containers and Akka.Net in F#
Actor Clustering with Docker Containers and Akka.Net in F#Riccardo Terrell
 
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Puppet
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akkanartamonov
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak SearchJustin Edelson
 
Introduction to Perl - Day 1
Introduction to Perl - Day 1Introduction to Perl - Day 1
Introduction to Perl - Day 1Dave Cross
 
Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4
Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4
Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4NETWAYS
 

What's hot (20)

Rack
RackRack
Rack
 
Intro to Perl and Bioperl
Intro to Perl and BioperlIntro to Perl and Bioperl
Intro to Perl and Bioperl
 
Concurrecny inf sharp
Concurrecny inf sharpConcurrecny inf sharp
Concurrecny inf sharp
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Introduction to Perl - Day 2
Introduction to Perl - Day 2Introduction to Perl - Day 2
Introduction to Perl - Day 2
 
Evolving Tests
Evolving TestsEvolving Tests
Evolving Tests
 
Bioinformatics p1-perl-introduction v2013
Bioinformatics p1-perl-introduction v2013Bioinformatics p1-perl-introduction v2013
Bioinformatics p1-perl-introduction v2013
 
Perl tutorial
Perl tutorialPerl tutorial
Perl tutorial
 
Perl programming language
Perl programming languagePerl programming language
Perl programming language
 
Introduction to Perl and BioPerl
Introduction to Perl and BioPerlIntroduction to Perl and BioPerl
Introduction to Perl and BioPerl
 
LPW: Beginners Perl
LPW: Beginners PerlLPW: Beginners Perl
LPW: Beginners Perl
 
Perl Introduction
Perl IntroductionPerl Introduction
Perl Introduction
 
Actor Clustering with Docker Containers and Akka.Net in F#
Actor Clustering with Docker Containers and Akka.Net in F#Actor Clustering with Docker Containers and Akka.Net in F#
Actor Clustering with Docker Containers and Akka.Net in F#
 
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akka
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak Search
 
Perl Basics with Examples
Perl Basics with ExamplesPerl Basics with Examples
Perl Basics with Examples
 
Introduction to Perl - Day 1
Introduction to Perl - Day 1Introduction to Perl - Day 1
Introduction to Perl - Day 1
 
Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4
Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4
Puppet Camp Berlin 2015: Martin Alfke | The Power of Puppet 4
 
Perl Scripting
Perl ScriptingPerl Scripting
Perl Scripting
 

Viewers also liked

Why the hardness test can not determine yield strength and the asme guide
Why the hardness test can not determine yield strength and the asme guideWhy the hardness test can not determine yield strength and the asme guide
Why the hardness test can not determine yield strength and the asme guideFahmy Haggag
 
Crew, FOIA,Documents 017782- 017823
Crew, FOIA,Documents 017782- 017823Crew, FOIA,Documents 017782- 017823
Crew, FOIA,Documents 017782- 017823Obama White House
 
Post-It Girl
Post-It GirlPost-It Girl
Post-It GirlLitWorld
 
Hollow - Recovering from Eating Disorders
Hollow - Recovering from Eating DisordersHollow - Recovering from Eating Disorders
Hollow - Recovering from Eating Disorderspyromarketing
 
PresentacióN.Ppt
PresentacióN.PptPresentacióN.Ppt
PresentacióN.Pptguest772b1f
 
Chase Oaks VBX - Monday - Greatness of the Journey
Chase Oaks VBX - Monday - Greatness of the JourneyChase Oaks VBX - Monday - Greatness of the Journey
Chase Oaks VBX - Monday - Greatness of the JourneyJason Loveless
 
What Is Literary Criticism[1]2
What Is Literary Criticism[1]2What Is Literary Criticism[1]2
What Is Literary Criticism[1]2makeefer
 
Chase Oaks VBX - Wednesday - The Sacrifice Of The Journey
Chase Oaks VBX - Wednesday - The  Sacrifice Of The  JourneyChase Oaks VBX - Wednesday - The  Sacrifice Of The  Journey
Chase Oaks VBX - Wednesday - The Sacrifice Of The JourneyJason Loveless
 
Annual Report: What's happening @ the Wadleigh 2009-2010
Annual Report: What's happening @ the Wadleigh 2009-2010Annual Report: What's happening @ the Wadleigh 2009-2010
Annual Report: What's happening @ the Wadleigh 2009-2010librarygrl3
 
P R I D I N A K A V I C O!!!
P R I D I  N A  K A V I C O!!!P R I D I  N A  K A V I C O!!!
P R I D I N A K A V I C O!!!Stelarosa .
 
Top lista najboljih poza u krevetu
Top lista najboljih poza u krevetuTop lista najboljih poza u krevetu
Top lista najboljih poza u krevetuStelarosa .
 
Power Point 802.3
Power Point 802.3Power Point 802.3
Power Point 802.3roby90f
 
AGUILAS 2009
AGUILAS 2009AGUILAS 2009
AGUILAS 2009paobazzi
 
New Media Presentation
New Media PresentationNew Media Presentation
New Media Presentationgaskinjo
 
D6D Portfolio
D6D PortfolioD6D Portfolio
D6D Portfoliobethleo
 
The ABC's of Dad and Me
The ABC's of Dad and MeThe ABC's of Dad and Me
The ABC's of Dad and Mesunnymel20
 

Viewers also liked (20)

Why the hardness test can not determine yield strength and the asme guide
Why the hardness test can not determine yield strength and the asme guideWhy the hardness test can not determine yield strength and the asme guide
Why the hardness test can not determine yield strength and the asme guide
 
Orm
OrmOrm
Orm
 
Crew, FOIA,Documents 017782- 017823
Crew, FOIA,Documents 017782- 017823Crew, FOIA,Documents 017782- 017823
Crew, FOIA,Documents 017782- 017823
 
Visita Uv
Visita UvVisita Uv
Visita Uv
 
Post-It Girl
Post-It GirlPost-It Girl
Post-It Girl
 
Hollow - Recovering from Eating Disorders
Hollow - Recovering from Eating DisordersHollow - Recovering from Eating Disorders
Hollow - Recovering from Eating Disorders
 
PresentacióN.Ppt
PresentacióN.PptPresentacióN.Ppt
PresentacióN.Ppt
 
Chase Oaks VBX - Monday - Greatness of the Journey
Chase Oaks VBX - Monday - Greatness of the JourneyChase Oaks VBX - Monday - Greatness of the Journey
Chase Oaks VBX - Monday - Greatness of the Journey
 
Hr2all offer to AIMS
Hr2all offer to AIMSHr2all offer to AIMS
Hr2all offer to AIMS
 
What Is Literary Criticism[1]2
What Is Literary Criticism[1]2What Is Literary Criticism[1]2
What Is Literary Criticism[1]2
 
Chase Oaks VBX - Wednesday - The Sacrifice Of The Journey
Chase Oaks VBX - Wednesday - The  Sacrifice Of The  JourneyChase Oaks VBX - Wednesday - The  Sacrifice Of The  Journey
Chase Oaks VBX - Wednesday - The Sacrifice Of The Journey
 
Annual Report: What's happening @ the Wadleigh 2009-2010
Annual Report: What's happening @ the Wadleigh 2009-2010Annual Report: What's happening @ the Wadleigh 2009-2010
Annual Report: What's happening @ the Wadleigh 2009-2010
 
P R I D I N A K A V I C O!!!
P R I D I  N A  K A V I C O!!!P R I D I  N A  K A V I C O!!!
P R I D I N A K A V I C O!!!
 
Top lista najboljih poza u krevetu
Top lista najboljih poza u krevetuTop lista najboljih poza u krevetu
Top lista najboljih poza u krevetu
 
Power Point 802.3
Power Point 802.3Power Point 802.3
Power Point 802.3
 
AGUILAS 2009
AGUILAS 2009AGUILAS 2009
AGUILAS 2009
 
Client Samples
Client SamplesClient Samples
Client Samples
 
New Media Presentation
New Media PresentationNew Media Presentation
New Media Presentation
 
D6D Portfolio
D6D PortfolioD6D Portfolio
D6D Portfolio
 
The ABC's of Dad and Me
The ABC's of Dad and MeThe ABC's of Dad and Me
The ABC's of Dad and Me
 

Similar to What is Rack middleware

Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record.toster
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyFabio Akita
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
Php my sql - functions - arrays - tutorial - programmerblog.net
Php my sql - functions - arrays - tutorial - programmerblog.netPhp my sql - functions - arrays - tutorial - programmerblog.net
Php my sql - functions - arrays - tutorial - programmerblog.netProgrammer Blog
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl TechniquesDave Cross
 
Rails 3 Beautiful Code
Rails 3 Beautiful CodeRails 3 Beautiful Code
Rails 3 Beautiful CodeGreggPollack
 
Ruby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails frameworkRuby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails frameworkPankaj Bhageria
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkBen Scofield
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Aura Project for PHP
Aura Project for PHPAura Project for PHP
Aura Project for PHPHari K T
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortegaarman o
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rackdanwrong
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportBen Scofield
 
Does your configuration code smell?
Does your configuration code smell?Does your configuration code smell?
Does your configuration code smell?Tushar Sharma
 

Similar to What is Rack middleware (20)

Intro to Rack
Intro to RackIntro to Rack
Intro to Rack
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Rack
RackRack
Rack
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em Ruby
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Php my sql - functions - arrays - tutorial - programmerblog.net
Php my sql - functions - arrays - tutorial - programmerblog.netPhp my sql - functions - arrays - tutorial - programmerblog.net
Php my sql - functions - arrays - tutorial - programmerblog.net
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Rails 3 Beautiful Code
Rails 3 Beautiful CodeRails 3 Beautiful Code
Rails 3 Beautiful Code
 
Ruby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails frameworkRuby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails framework
 
Arrays in php
Arrays in phpArrays in php
Arrays in php
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Aura Project for PHP
Aura Project for PHPAura Project for PHP
Aura Project for PHP
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 
Does your configuration code smell?
Does your configuration code smell?Does your configuration code smell?
Does your configuration code smell?
 

Recently uploaded

Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 

Recently uploaded (20)

Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 

What is Rack middleware

  • 1. Rack Middleware David Dollar
  • 3. A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 4. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 5. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 6. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 7. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 8. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 9. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 10. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 11. lambda do |environment| [ 200, { 'Content-Type' => 'text/plain' }, [ 'OK' ] ] end A Rack application is a Ruby object that responds to call. It takes exactly one argument, the environment. It returns an Array of exactly three values: The status, the headers, and the body. The headers should respond to each and yield key/value pairs. The body should respond to each and yield String objects.
  • 16. Before Rails 2.3 Apache Passenger Rails
  • 17. Before Rails 2.3 Apache Passenger Rails After Rails 2.3
  • 18. Before Rails 2.3 Apache Passenger Rails After Rails 2.3 Apache
  • 19. Before Rails 2.3 Apache Passenger Rails After Rails 2.3 Apache Passenger
  • 20. Before Rails 2.3 Apache Passenger Rails After Rails 2.3 Apache Passenger Rails
  • 21. Before Rails 2.3 Apache Passenger Rails After Rails 2.3 Apache Passenger Rails
  • 22. Passenger ActionController::Base#call(env) Rails
  • 24. Passenger ActionController::Base#call(env) Rails
  • 25. Passenger Middleware Rails
  • 26. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 27. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 28. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 29. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 30. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 31. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 32. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 33. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 34. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, do_api_call(env) ] else env['mydata'] = 'test' @next_in_chain.call(env) end end end
  • 38. App Server Rack::Cache Rails Storage
  • 39. App Server Rack::Cache Rails Storage
  • 41.
  • 42.
  • 43.
  • 45. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 46. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 47. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 48. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 49. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 50. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 51. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 52. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 53. class SessionsController def new render :new # contains a textbox called quot;identityquot; end def create if openid = request.env['rack.openid.response'] case openid.status when :success # ... when :failure # ... end else response.headers['WWW-Authenticate'] = Rack::OpenID.build_header( :identifier => params[:identity] ) render :text => '', :status => 401 end end end
  • 55. # app/controllers/users_controller.rb @user = User.find(params[:id]) debugger render :show # run the rake task, $ rake debug Connected. # refresh a page in your browser, your app will break at debugger statements (rdb:1) p @user <User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
  • 56. # app/controllers/users_controller.rb @user = User.find(params[:id]) debugger render :show # run the rake task $ rake debug Connected. (rdb:1) p @user <User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
  • 57. # app/controllers/users_controller.rb @user = User.find(params[:id]) debugger render :show # run the rake task $ rake debug Connected. (rdb:1) p @user <User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
  • 58. # app/controllers/users_controller.rb @user = User.find(params[:id]) debugger render :show # run the rake task $ rake debug Connected. (rdb:1) p @user <User id: 1, name: quot;David Dollarquot;, email: quot;ddollar@gmail.comquot;>
  • 60. Passenger Middleware Rails class ExampleMiddleware def initialize(next_in_chain) @next_in_chain = next_in_chain end def call(env) if env['PATH_INFO'] =~ Regexp.new('^/api') [ 200, { 'Content-Type' => 'text/xml' }, '<?xml?>' ] else @next_in_chain.call(env) end end end
  • 61. Passenger Middleware Rails class ExampleMiddleware # ... end # config/environment.rb config.middleware.use 'ExampleMiddleware'
  • 62. Passenger Middleware Rails class ExampleMiddleware # ... end # config/environment.rb config.middleware.use 'ExampleMiddleware'
  • 63. Passenger Middleware Sinatra class ExampleMiddleware # ... end app = Rack::Builder.new do use ExampleMiddleware run MySinatraApp.new end
  • 64. Passenger Middleware Sinatra class ExampleMiddleware # ... end app = Rack::Builder.new do use ExampleMiddleware run MySinatraApp.new end
  • 65. Passenger Middleware Sinatra class ExampleMiddleware # ... end app = Rack::Builder.new do use ExampleMiddleware run MySinatraApp.new end
  • 66. class ExampleMiddleware # ... end # Rails config.middleware.use 'ExampleMiddleware' # Rack::Builder app = Rack::Builder.new do use ExampleMiddleware run MySinatraApp.new end
  • 67. class ExampleMiddleware # ... end # Rails config.middleware.use 'ExampleMiddleware' config.middleware.use 'ExampleMiddlewareTwo' # Rack::Builder app = Rack::Builder.new do use ExampleMiddleware use ExampleMiddlewareTwo run MySinatraApp.new end
  • 68. class ExampleMiddleware # ... end # Rails config.middleware.use 'ExampleMiddleware' config.middleware.use 'ExampleMiddlewareTwo' config.middleware.use 'ExampleMiddlewareThree' # Rack::Builder app = Rack::Builder.new do use ExampleMiddleware use ExampleMiddlewareTwo use ExampleMiddlewareThree run MySinatraApp.new end

Editor's Notes

  1. To start off, we should take a brief look at Rack itself.
  2. This is a valid Rack application.
  3. lambda takes a block and creates a Proc object. Proc objects are invoked using the call method.
  4. This proc object takes one argument, the environment.
  5. And returns three values, the status code...
  6. The response headers (here we&#x2019;re setting the Content Type to text/plain) ...
  7. and the response body (here the string &#x201C;OK&#x201D;)
  8. A Ruby Hash responds to each and returns key/value pairs
  9. This array responds to each and returns Strings
  10. Rack was introduced to Rails in version 2.3.
  11. Before Rack, a typical Rails stack in production would look like...
  12. A Web Server
  13. Some kind of application server (Mongrel, Thin, etc)..
  14. Your application.
  15. Now that we have Rack, this stack looks like...
  16. A web server...
  17. An application server...
  18. And your application. No difference. From a Rails developer&#x2019;s perspective, not much has changed at first glance.
  19. The magic happens here. Rails is now Rack compatible, and this interconnect now takes the form of the Rack API.
  20. The Rack API is encapsulated in Rails by ActionController::Base...
  21. Which has a call method...
  22. That takes the environment as a parameter...
  23. And returns a status code...
  24. The response headers...
  25. And the response body.
  26. There are many reasons this change is important, but the one I&#x2019;m going to talk about is Middleware. What is Rack Middleware?
  27. Because we know what the API between the app server and the Rails stack looks like now. And Because we know what inputs it is expecting. And because we know what the return will look like.
  28. We can now insert code in between the app server and the application, that can speak this Rack API. We call this code Middleware.
  29. A middleware application takes the form of a class...
  30. Its constructor...
  31. ...takes the next piece of the chain as a parameter, which allows you to keep the chain going.
  32. In this middleware, which has a call method...
  33. ...and takes the environment as a parameter...
  34. We&#x2019;re going to check a value in the environment, the requested path, and see if it starts with /api
  35. If it does, we&#x2019;re going to return an array of three values, A status code, the headers, and the body
  36. Otherwise, we&#x2019;re going to add some data to the environment. We can put any ruby objects we like in here for the benefit of applications further down the chain.
  37. And we&#x2019;re going to pass the call through to the next item in the chain.
  38. Rack::Cache sits in the middle of your application stack and monitors requests. It understands HTTP standards for both freshness (Expires, Cache-Control headers) and validation (Last-Modified, ETag headers)
  39. It can intercept requests and serve them from its own storage. (Disk, memcached, memory) Cache expiration and invalidation is handled automatically.
  40. Rack::Bug adds a toolbar to the top of your app to give you some insight into the internals.
  41. You can look at things like the Rails Environment
  42. You can look at which queries ran on the page and how long they took. You can run an EXPLAIN on them right from the page.
  43. Rack::OpenID takes care of OpenID authentication for you
  44. In your SessionsController which controls user authentication...
  45. ...you have a &#x201C;new&#x201D; method which renders a form that contains an identity textbox for the user to type their OpenID URL
  46. In the create action, which processes the form
  47. We check the environment to see if Rack::OpenID has injected credentials On the first pass through this will be missing, so...
  48. We build a header that Rack::OpenID will be able to process...
  49. ...that includes the OpenID identity provided by the user
  50. which in combination with a 401 status code lets Rack::OpenID know to take over
  51. After Rack::OpenID does its thing it injects &#x2018;rack.openid.response&#x2019; into the environment. So when we come back into the controller and the OpenID credentials are present in the environment...
  52. We can check the status of the OpenID response and take the appropriate action.
  53. Rack::Debug gives an easy interface to ruby-debug inside your application
  54. Add debugger statements to your code
  55. At the console, run the debug rake task
  56. The next time you refresh a page in your browser, your app stops at debugger statements and drops you into an interactive shell.
  57. How do I use Middleware in my applications.
  58. If I have a middleware called ExampleMiddleware
  59. In Rails, I&#x2019;m going to go to my config/environment.rb
  60. And add a line, config.middleware.use &#x2018;ExampleMiddleware&#x2019;
  61. Rack also gives us a class called Rack::Builder
  62. We tell it to use our Middleware