简体   繁体   中英

Rack Middleware: use and run constructs

I am reading this article on Rack Middleware. It states the following:

Rack is more than interface that can be used to talk to web server. It's used to group and order modules , which are usually Ruby classes, and specify dependency between them. Rack::Builder puts these modules on top of each other, creating stack-like structure of final web application .

So basically, we can use ruby classes to stack middleware on top of each other. We simply need a reference to the next middleware - kind of reminds me of the decorator design pattern.

All we need to do is have a constructor that takes the next application (middleware in the stack) as a paraemter. Second, we need to define a call method, which takes the environment hash as a parameter and returns an array of status code, environment hash and response body.

This is the example provided:

# shrimp.rb
class Shrimp
  def initialize(app)
    @app = app       
  end                

  def call(env)      
    @app.call(env)   
  end                
end                  

# config.ru
require 'rack'
require 'rack/lobster'
require 'shrimp'      

use Shrimp            
run Rack::Lobster.new </pre> 

According to the Rack documentation, The use method adds middleware to the stack, and the run method dispatches to an application. I'm a little confused by this syntax. use adds Shrimp to the middleware stack and run passes Lobster instance into the Shrimp constructor? I am still confused by the role of run here.

The article you have linked to mentions that Rack comes with a sample application Lobster so yes, for a start, that is an app.

The Shrimp class is just a Ruby class which is how a middleware should be written.

In the config.ru file, you require the modules, register the middleware, and then run the application.

use adds Shrimp to the middleware stack and run passes Lobster instance into the Shrimp constructor?

You are right when you say use adds Shrimp to the middleware stack but run does not necessarily pass a Lobster instance into the Shrimp constructor. run just executes the Rack application and passing the app instance is how Rack works internally. The real thing happens in the use part where you register the middleware.

For example:

# config.ru
require 'rack'
require 'rack/lobster'
require 'shrimp_1'     
require 'shrimp_2'     
require 'shrimp_3'      

use Shrimp_1      
use Shrimp_2      
use Shrimp_3            
run Rack::Lobster.new </pre>

All three Shrimp classes will be passed the app(Lobster) instance in that order and this will be handled by Rack itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM