RubyのRackミドルウェアとは何ですか?「ミドルウェア」の意味については、良い説明が見つかりませんでした。
9 に答える
ラック・アズ・デザイン
Rack ミドルウェアは、「要求と応答をフィルター処理する方法」以上のものです。これは、Rackを使用した Web サーバーのパイプライン設計パターンの実装です。
リクエストを処理するさまざまな段階を非常に明確に分離します。適切に設計されたすべてのソフトウェア製品の主要な目標は、関心の分離です。
たとえば、Rack を使用すると、パイプラインの個別のステージを次のように実行できます。
認証: 要求が到着したとき、ユーザーのログオンの詳細は正しいですか? この OAuth、HTTP 基本認証、名前/パスワードを検証するにはどうすればよいですか?
Authorization : 「ユーザーはこの特定のタスクを実行する権限がありますか?」、つまりロールベースのセキュリティ。
キャッシング: このリクエストは既に処理済みですが、キャッシュされた結果を返すことはできますか?
装飾: 下流の処理を改善するためにリクエストを強化するにはどうすればよいですか?
パフォーマンスと使用状況の監視: リクエストとレスポンスからどのような統計情報を取得できますか?
実行: 実際にリクエストを処理し、レスポンスを提供します。
さまざまな段階を分離できる (およびオプションでそれらを含めることができる) ことは、適切に構造化されたアプリケーションを開発する上で非常に役立ちます。
コミュニティ
また、Rack Middleware を中心に開発されている優れたエコシステムもあります。上記のすべての手順やその他の手順を実行するために、事前に構築されたラック コンポーネントを見つけることができるはずです。ミドルウェアのリストについては、Rack GitHub wiki を参照してください。
ミドルウェアとは
ミドルウェアは、何らかのタスクの実行を支援するが直接関与しないソフトウェア コンポーネント/ライブラリを指す恐ろしい用語です。非常に一般的な例は、ロギング、認証、およびその他の一般的な水平処理コンポーネントです。これらは、複数のアプリケーションで誰もが必要とするものですが、自分で構築することに興味を持っている (またはそうすべきである) 人はあまり多くありません。
詳しくは
リクエストをフィルタリングする方法であるというコメントは、おそらくRailsCast のエピソード 151: Rack Middlewareのスクリーン キャストから来ています。
Rack ミドルウェアは Rack から進化したもので、Introduction to Rack middleware に優れたイントロがあります。
ウィキペディアのミドルウェアの紹介がここにあります。
まず、Rack はまさに次の 2 つです。
- Web サーバー インターフェイスの規約
- 宝石
ラック - ウェブサーバー インターフェイス
ラックの基本は単純な規則です。ラックに準拠したすべての Web サーバーは、指定したオブジェクトに対して常に call メソッドを呼び出し、そのメソッドの結果を提供します。Rack は、この call メソッドがどのように見える必要があるか、および何を返さなければならないかを正確に指定します。それがラックです。
簡単に試してみましょう。ラックに準拠した Web サーバーとして WEBrick を使用しますが、どれでも構いません。JSON 文字列を返す単純な Web アプリケーションを作成しましょう。このために、config.ru というファイルを作成します。config.ru は、rack gem のコマンド rackup によって自動的に呼び出されます。これは、config.ru の内容をラック準拠の Web サーバーで実行するだけです。それでは、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 というメソッドがあり、環境ハッシュを受け取り、Web サーバーが提供する [status, headers, body] の形式の配列を返します。Rackup を呼び出すだけで試してみましょう。デフォルトのラック準拠サーバー、おそらく 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
URLをカールするか、アクセスして、新しいJSONサーバーをテストしましょうhttp://localhost:9292/hello.json
。
$ curl http://localhost:9292/hello.json
{ message: "Hello!" }
できます。すごい!これは、Rails であれ Sinatra であれ、すべての Web フレームワークの基礎です。ある時点で call メソッドを実装し、すべてのフレームワーク コードを処理し、最後に典型的な [ステータス、ヘッダー、本文] 形式で応答を返します。
たとえば、Ruby on Rails では、ラック リクエストは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 で応答します。したがって、ラック インターフェイス規則に準拠しているすべての 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
作成されると、実際のラック アプリケーションのコピーが保存されます。私たちの場合、それは JSONServer のインスタンスです。Rack はミドルウェアで call メソッドを自動的に呼び出し、[status, headers, body]
JSONServer が返すのと同じように配列を返します。
したがって、このミドルウェアでは、開始点が取得され、JSONServer への実際の呼び出しが で行われ@app.call(env)
、ロガーがログ エントリを出力し、最終的に応答を として返します[@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 を使用すると、追加された順序で呼び出される複数のミドルウェアを追加できます。これは、ラック アプリケーションのコアを変更せずに機能を追加する優れた方法です。
ラック - ザ・ジェム
ラックは、まず第一に、慣例ですが、優れた機能を提供する宝石でもあります。そのうちの 1 つは、すでに JSON サーバーで使用している Rackup コマンドです。しかし、もっとあります!ラックジェムは、静的ファイルやディレクトリ全体の提供など、多くのユースケースに対応する小さなアプリケーションを提供します。単純なファイルを提供する方法を見てみましょう。たとえば、htmls/index.html にある非常に基本的な HTML ファイルです。
<!DOCTYPE HTML>
<html>
<head>
<title>The Index</title>
</head>
<body>
<p>Index Page</p>
</body>
</html>
このファイルをウェブサイトのルートから提供したいので、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 ファイルのリストが表示されます。
私はかなりの時間、Rack を理解するのに苦労しました。このミニチュア Ruby Web サーバーを自分で作成して初めて、完全に理解できました。Rack について学んだことを (ストーリーの形で) ブログで共有しました: http://blog.gauravchande.com/what-is-rack-in-ruby-rails
フィードバックは大歓迎です。
config.ru
最小限の実行可能な例
app = Proc.new do |env|
[
200,
{
'Content-Type' => 'text/plain'
},
["main\n"]
]
end
class Middleware
def initialize(app)
@app = app
end
def call(env)
@status, @headers, @body = @app.call(env)
[@status, @headers, @body << "Middleware\n"]
end
end
use(Middleware)
run(app)
実行rackup
して訪問しlocalhost:9292
ます。出力は次のとおりです。
main
Middleware
Middleware
したがって、メイン アプリをラップして呼び出すことは明らかです。したがって、リクエストを前処理し、レスポンスを後処理することができます。
http://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stackで説明されているように、Rails はその機能の多くに Rack ミドルウェアを使用しており、config.middleware.use
ファミリ メソッドを使用して独自のものを追加することもできます。
ミドルウェアに機能を実装する利点は、Rails だけでなくすべての主要な Ruby フレームワークで再利用できることです。