如何运行一个只包含中间件的简单Ruby Rack应用程序?

时间:2016-10-28 17:22:05

标签: ruby rack

我有一个简单的Ruby Rack应用程序,它只包含中间件。我真的不需要“应用程序”,因为中间件可以完成我想要的任何事情。如何定义我的config.ru仅将中间件作为应用程序运行?

require "some_middleware"
use SomeMiddleware
run -> {|env| [200, {"Content-Type" => "text/plain"}, ["I don't need this part!"]] }

1 个答案:

答案 0 :(得分:2)

Rack应用程序(包括中间件)基本上只是一个响应call的对象,接受描述请求的哈希并返回描述响应的数组。

使用rackup文件时,Rack使用Rack::Builder中描述的DSL。 run method just sets the “base” app

def run(app)
  @run = app
end

use方法存储您希望包含在应用中的中间件类,然后在构建最终应用时为每个应用执行类似的操作(与它们在{{1}中的显示方式相反的顺序文件):

config.ru

这比这复杂一点,但这是一般的想法。创建中间件类的新实例,将现有应用程序作为构造函数的第一个参数传递,结果对象成为新应用程序。这是Rack中间件的“没有详细记录”的“接口”:它的初始化器的第一个参数是它正在包装的应用程序,其余的是传递给@run = MiddleWare.new(@run, other_args) 的任何其他参数。

DSL期望始终存在userun语句,如果省略两者,则会出现错误。

如果您的中间件是以这样的方式编写的,它可以处理没有传递给其初始化程序的参数,并且它的行为就像一个完整的应用程序,那么您可以直接将其用作map中的应用程序:

config.ru

这就是Sinatra允许used as middleware做的事情。它stores the app in the initializer如果给出,然后当一个请求到达时与任何路由不匹配时它会使用@app to decide whether to behave as middleware的存在并传递请求,或者表现为最终应用并对其进行处理作为一个未找到的错误。

如果您的中间件没有这种灵活性,那么您将需要提供一个应用程序来包装它,就像您的示例中所示。在这种情况下,如果中间件没有正确处理请求并尝试将其传递给包装的应用程序,那么让应用程序进行错误处理也是有用的。

如果您想避免在run SomeMiddleware.new 中使用单独的userun语句,则可以使用config.ru,并将一个简单的应用直接传递到您的中间件:

run

请注意这是如何遵循上面介绍的中间件接口的:初始化程序的第一个参数是要包装的应用程序。