Rack中间件是什么?

12 浏览
0 Comments

Rack中间件是什么?

Ruby中的Rack中间件是什么?我找不到任何好的解释来说明他们所谓的\"中间件\"是什么。

admin 更改状态以发布 2023年5月23日
0
0 Comments

首先,Rack确切地说有两个方面:

  • 一个Web服务器接口规定
  • 一个gem

Rack - Web服务器接口

Rack的基本原理是一个简单的规定。每个符合Rack标准的Web服务器总是会在你提供的对象上调用一个call方法,并返回该方法的结果。Rack确切地规定了这个方法的调用方式和返回值。这就是Rack。

我们来试一试。我将使用符合Rack标准的Web服务器WEBrick,但其他服务器也都可以。让我们创建一个简单的Web应用程序,它返回一个JSON字符串。为此,我们将创建一个名为config.ru的文件。配置文件config.ru将自动由Rack gem的命令rackup调用,该命令会在符合Rack标准的Web服务器中运行config.ru的内容。因此,我们来将以下内容添加到config.ru文件:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end
map '/hello.json' do
  run JSONServer.new
end

根据规定,我们的服务器有一个名为call的方法,它接受一个环境哈希并返回一个形如[status,headers,body]的数组,供Web服务器提供服务。我们来试一试,只需简单地调用rackup即可。一个默认的符合Rack规范的服务器,例如WEBrick或Mongrel,将启动并立即等待请求。

$ rackup
[2012-02-19 22:39:26] INFO  WEBrick 1.3.1
[2012-02-19 22:39:26] INFO  ruby 1.9.3 (2012-01-17) [x86_64-darwin11.2.0]
[2012-02-19 22:39:26] INFO  WEBrick::HTTPServer#start: pid=16121 port=9292

我们来通过curl或访问url http://localhost:9292/hello.json来测试我们的新JSON服务器,结果如下:

$ curl http://localhost:9292/hello.json
{ message: "Hello!" }

它可以工作。太好了!这是每个Web框架的基础,无论是Rails还是Sinatra。它们都会实现一个call方法,在整个框架代码中运行,并最终以典型的[status,headers,body]格式返回响应。

例如,在Ruby on Rails中,Rack请求会打到ActionDispatch::Routing.Mapper类,代码如下:

module ActionDispatch
  module Routing
    class Mapper
      ...
      def initialize(app, constraints, request)
        @app, @constraints, @request = app, constraints, request
      end
      def matches?(env)
        req = @request.new(env)
        ...
        return true
      end
      def call(env)
        matches?(env) ? @app.call(env) : [ 404, {'X-Cascade' => 'pass'}, [] ]
      end
      ...
  end
end

因此,基本上Rails根据env哈希的依赖性检查是否有任何匹配的路由。如果匹配,则将env哈希传递给应用程序以计算响应,否则立即使用404响应。因此,符合Rack接口规范的任何Web服务器都能够提供完全成熟的Rails应用程序。

中间件

Rack还支持创建中间件层。它们基本上会拦截请求,对其进行某些操作,然后将其传递。这非常适用于多种任务。

假设我们想在我们的JSON服务器中添加记录,记录还会测量请求需要多长时间。我们可以简单地创建一个这样的中间件记录器:

class RackLogger
  def initialize(app)
    @app = app
  end
  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)
    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

当它被创建时,它会保存实际的Rack应用程序副本。在我们的例子中,这是一个JSON服务器实例。Rack自动在中间件上调用call方法,并期望返回一个[status,headers,body]数组,就像我们的JSON服务器返回的那样。

因此,在这个中间件中,会取出起点,然后使用@app.call(env)进行实际调用JSON服务器,然后记录器输出记录条目,最后返回响应作为[@status,@headers,@body]

为了让我们的小网站rackup.ru使用这个中间件,可以像这样添加一个use RackLogger:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end
class RackLogger
  def initialize(app)
    @app = app
  end
  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)
    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end
use RackLogger
map '/hello.json' do
  run JSONServer.new
end   

重启服务器,轻轻松松地输出每个请求的日志。Rack允许你添加多个中间件,按照他们添加的顺序调用。这只是一个在不改变rack应用程序核心的情况下添加功能的绝佳方法。

Rack - The Gem

Rack不仅是一种约定,也是提供了很多功能的gem。其中之一是我们已经为JSON服务器使用过的rackup命令。但还有更多!rack gem为许多用例提供了小型应用程序,例如提供静态文件或整个目录。让我们看看如何提供一个简单的文件,例如位于htmls/index.html的非常基本的HTML文件:


  
  
    The Index
  
  
    

Index Page

我们可能希望从网站根目录提供此文件,因此让我们将以下内容添加到我们的config.ru中:

map '/' do
  run Rack::File.new "htmls/index.html"
end

如果我们访问http://localhost:9292,我们会看到我们的HTML文件完美地呈现出来。这很容易,是吧?

让我们通过在/javascripts下创建一些JavaScript文件并将以下内容添加到config.ru中来添加整个JavaScript文件目录:

map '/javascripts' do
  run Rack::Directory.new "javascripts"
end

重新启动服务器,访问http://localhost:9292/javascript,您将看到所有JavaScript文件的列表,现在可以从任何地方直接包含它们。

0
0 Comments

Rack作为设计

Rack中间件不仅是“过滤请求和响应的方法” - 它是使用Rack针对Web服务器实现管道设计模式的实现。

它非常清晰地分离了处理请求的不同阶段 - 分离关注点是所有设计良好的软件产品的关键目标。

例如,使用Rack,我可以有独立的管道阶段执行以下操作:

  • 身份验证:请求到达时,用户的登录详细信息是否正确?如何验证OAuth、HTTP基本身份验证、名称/密码?

  • 授权:用户是否被授权执行特定任务?

  • 缓存:我是否已经处理过这个请求?可以返回缓存结果吗?

  • 装饰:如何增强请求以使下游处理更好?

  • 性能和使用情况监控:可以从请求和响应中获取什么统计信息?

  • 执行:实际处理请求并提供响应。

能够分离不同的阶段(并可选择包含它们)有助于开发良好结构化的应用程序。

社区

围绕Rack中间件还有一个伟大的生态系统正在发展 - 您应该能够找到预先构建的Rack组件来执行上述所有步骤以及更多操作。请参见Rack GitHub Wiki的中间件列表

中间件是什么?

中间件是指任何辅助但不直接参与某个任务执行的软件组件/库。非常常见的例子是日志记录、身份验证和其他通用的、水平处理组件。这些通常是每个应用都需要的东西,但不太需要太多人(或不应该)自己构建。

更多信息

0