在通用机架应用程序中获取中间件的有序列表?

Posted

技术标签:

【中文标题】在通用机架应用程序中获取中间件的有序列表?【英文标题】:Get ordered list of middleware in a generic rack application? 【发布时间】:2011-04-29 19:29:11 【问题描述】:

我正在寻找的功能类似于 Rails 中的rake middleware 命令,除了通用机架应用程序。

【问题讨论】:

【参考方案1】:

这早就该了,我知道

here's a nice thread,最终答案是最后一个帖子

根据 Marc-Andre 的评论更新:

以下是此link的最后一篇帖子

Rack 没有这样的机制,而且由于不是所有的中间件都是通过@middleware 添加的,Sinatra 无法告诉你使用了什么中间件。顺便说一句,rails 也不能,它只能告诉你什么是可能的。中间件不必是线性列表(即使用机架路由器或其他东西时)。

【讨论】:

-1。 SO的全部意义在于不必通过帖子列表。复制并改进正确答案并将该链接添加为来源。【参考方案2】:

这将返回机架应用程序的所有中间件的列表:

def middleware_classes(app)
  app.instance_variable_get(:@use).map|middleware| middleware.call.class.name 
end

app = Rack::Builder.parse_file('config.ru').first; nil # trailing nil to avoid paging in an interactive console
p middleware_classes(app)

【讨论】:

+1 就像一个魅力。我将所有这些都放入了test-rack.rb 脚本并通过ruby test-rack.rb 运行它。 (编辑问题以添加缺少的机架要求;)【参考方案3】:
$ rake middleware

use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007ffd148f9468>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run RackTest::Application.routes

http://pothibo.com/2013/11/ruby-on-rails-inside-actiondispatch-and-rack/

【讨论】:

从描述中,很明显他知道rake middleware。他想要这个用于非 Rails 应用程序。【参考方案4】:

如果您使用的是扩展 Sinatra::Base 的 Sinatra 应用程序,我必须使用 Michael Hale 答案的略微修改版本:

require 'rack'
​
def middleware_classes(app)
  r = [app]
  ​
  while ((next_app = r.last.instance_variable_get(:@app)) != nil)
    r << next_app
  end
  ​
  r.map|e| e.instance_variable_defined?(:@app) ? e.class : e 
end
​
sinatra_app = Rack::Builder.parse_file('config.ru').first
sinatra_rack_builder = sinatra_app.build(sinatra_app)
sinatra_extended_app = sinatra_rack_builder.to_app
rack_app = sinatra_extended_app.app

pp middleware_classes(rack_app)

​ 将其放入 dump_middleware.rb 之类的文件后,我能够按预期看到中间件:

$ bundle exec ruby ./dump_middleware.rb
[Rack::Head,
 Rack::NullLogger,
 Rack::Session::Cookie,
 Rack::Protection::FrameOptions,
 Rack::Protection::HttpOrigin,
 Rack::Protection::IPSpoofing,
 Rack::Protection::JsonCsrf,
 Rack::Protection::PathTraversal,
 Rack::Protection::RemoteToken,
 Rack::Protection::SessionHijacking,
 Rack::Protection::XSSHeader,
 Warden::Manager,
 SinatraApp]

可能有更简洁的方法来做到这一点。

【讨论】:

【参考方案5】:

试试 Konstantin Haase 的 rack-graph gem。

由于某种原因,Konstantin 认为不适合在 ruby​​gems 上发布此 gem,因此您需要使用 git 将其添加到 Gemfile 或在本地安装和引用它。

# Gemfile
gem 'rack-graph', github: 'rkh/rack-graph'

$ bundle exec rackup -s Graph
# Locally (without bundler/Gemfile):
$ git clone https://github.com/rkh/rack-graph.git
$ ruby -I/path/to/rack-graph/lib $(which rackup) -s Graph

给定以下示例 Rack 应用程序:

# config.ru
Foo = proc  [200, , ['Foo']] 
App = proc  [200, , ['Ok']] 

map '/foo' do
  use Rack::Runtime
  use Rack::MethodOverride
  run Foo
end

run App

这是输出:

# Output:
Rack::ContentLength
 |- Rack::CommonLogger(stderr)
    |- Rack::ShowExceptions
       |- Rack::Lint
          |- Rack::TempfileReaper
             |- Rack::URLMap
                |- "/foo"
                |  |- Rack::Runtime
                |     |- Rack::MethodOverride
                |        |- Proc(0x00007fd93a97c2d0 /Users/steve/ruby/config.ru:1)
                |
                |- ""
                   |- Proc(0x00007fd93a97c2a8 /Users/steve/ruby/config.ru:2)

【讨论】:

以上是关于在通用机架应用程序中获取中间件的有序列表?的主要内容,如果未能解决你的问题,请参考以下文章

机架攻击阻止列表不起作用

什么是机架?我可以用它用 Ruby 构建 Web 应用程序吗?

二分查找

[pixhawk笔记]3-架构概览

《图解算法》--二分查找选择排序递归

如何以某种通用方式删除有序对多 CoreData 关系中的对象?