Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rackとは?Ruby開発者のための基本仕組みと自作ミドルウェア入門

RailsやSinatraなど、あらゆるRuby製Webフレームワークの裏側では、何が起こっているのでしょうか?

その答えがRackです。フレームワークとサーバーをつなぐ、まさに要となる存在です。

では、Rackとは一体何なのでしょうか?

Rackは、Webフレームワーク(Railsなど)とアプリケーションサーバー(Pumaなど)の間に位置する「層」です。

Rackとは?Ruby開発者のための基本仕組みと自作ミドルウェア入門

両者が正しくやり取りできるようにする、糊(グルー)のような役割を担っています。

なぜRackを使うのか?

Rackを使う最大の理由は、異なるフレームワークとサーバーを自由に組み合わせられるようにするためです。

それぞれが差し替え可能なプラグイン部品になります。

つまり、PumaはRailsでもSinatraでも、その他のRack互換フレームワークでも使えます。Rackインターフェースを実装していれば、どのフレームワークとどのサーバーを組み合わせても問題ありません。

Rackのおかげで、各コンポーネントは自分の役割に集中でき、みんなハッピーというわけです!

Rackミドルウェアとは?

RackはすべてのWebリクエストとレスポンスの間に介在しています。

そのため、不要なリクエストを拒否する「門番」として働いたり、遅いレスポンスを記録する「記録係」として働いたりすることができます。

これこそがRackミドルウェアです!

ミドルウェアとは、リクエスト・レスポンスのサイクルの一部として呼び出され、何らかの処理を行う機会を得る小さなRubyプログラムのことです。

具体的にはどんな用途があるのでしょうか?

  • ロギング(ログ出力)
  • セッション管理
  • プロファイリング(リクエスト完了までの所要時間の計測)
  • キャッシュ
  • セキュリティ(IPアドレスによるアクセス拒否、リクエスト数の制限など)
  • 静的ファイルの配信(CSS、JS、画像など)

これらは非常に便利な機能で、Rails自身もミドルウェアを活用して多くの機能を実装しています

Railsプロジェクト内でrake middlewareコマンドを実行すると、使用中のミドルウェアの一覧を確認できます。

さて、先ほど触れたRackインターフェースとは、どのようなものでしょうか?

実際の例を見てみましょう…

自作Rackアプリケーションの書き方

Rackの動きを理解する一番の近道は、実際に自分でアプリケーションを書いてみることです。

やってみましょう!

Rackアプリケーションとは、callメソッドを1つだけ持つクラスのことです。

次のような形になります:

require 'rack'

handler = Rack::Handler::Thin

class RackApp
  def call(env)
    [200, {"Content-Type" => "text/plain"}, "Hello from Rack"]
  end
end

handler.run RackApp.new

このコードを実行すると、ポート8080でサーバーが起動します(ぜひ試してみてください!)。

さて、返されているこの配列は何を意味しているのでしょうか?

  • HTTPステータスコード(200)
  • HTTPヘッダー("Content-Type")
  • レスポンス本文("Hello from Rack")

リクエストの詳細情報にアクセスしたい場合は、env引数を使います。

次のように記述します:

req = Rack::Request.new(env)

利用できる主なメソッドは以下の通りです:

  • path_info(パス情報。例:/articles/1)
  • ip(ユーザーのIPアドレス)
  • user_agent(Chrome、Firefox、Safariなど)
  • request_method(get / post)
  • body(リクエスト本文)
  • media_type(plain、json、htmlなど)

これらの情報を活用して、独自のRackアプリケーションを構築できます。

例えば、IPアドレスが5.5.5.5の場合にコンテンツへのアクセスを拒否してみましょう。

コードはこちらです:

require 'rack'

handler = Rack::Handler::Thin

class RackApp
  def call(env)
    req = Rack::Request.new(env)

    if req.ip == "5.5.5.5"
      [403, {}, ""]
    else
      [200, {"Content-Type" => "text/plain"}, "Hello from Rack"]
    end
  end
end

handler.run RackApp.new

効果を確認したい場合は、アドレスを127.0.0.1に変更してみてください。

うまくいかない場合は、localhostのIPv6版である::1を試してみましょう。

Rackミドルウェアの書き方と使い方

それでは、アプリケーションとミドルウェアを連携させて一緒に動かすには、どうすればよいのでしょうか?

答えはRack::Builderを使うことです。

理解するには、やはり例を見るのが一番です。

まず、Rackアプリ本体です:

require 'rack'

handler = Rack::Handler::Thin

class RackApp
  def call(env)
    req = Rack::Request.new(env)

    [200, {"Content-Type" => "text/plain"}, "Hello from Rack - #{req.ip}"]
  end
end

続いて、ミドルウェアです:

class FilterLocalHost
  def initialize(app)
    @app = app
  end

  def call(env)
    req = Rack::Request.new(env)

    if req.ip == "127.0.0.1" || req.ip == "::1"
      [403, {}, ""]
    else
      @app.call(env)
    end
  end
end

そして、両者を組み合わせる方法がこちらです:

app =
Rack::Builder.new do |builder|
  builder.use FilterLocalHost
  builder.run RackApp.new
end

handler.run app

この例では、2つのRackアプリケーションが登場します:

  • IPチェックを担当するもの(FilterLocalHost)
  • コンテンツ本体(HTML、JSONなど)を配信するアプリケーション

@app.call(env)という部分に注目してください。これこそが、FilterLocalHostをミドルウェアたらしめているポイントです。

起こり得るのは次の2つのどちらかです:

  • レスポンスを返して、そこでミドルウェアチェーンを終了させる
  • @app.call(env)でリクエストを次のミドルウェア、またはアプリ本体へ渡す

さらに、ミドルウェアを含むRackアプリのどの段階でも、レスポンスを加工・変更することができます。

例を見てみましょう:

class UpcaseAll
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)

    response.upcase!

    [status, headers, response]
  end
end

これが、まさにRackの仕組みです 🙂

まとめ

今回は、RubyのWebフレームワークとサーバーのやり取りを支えるインターフェース「Rack」について学びました。また、自作のRackアプリケーションを書くことで、その内部動作もきっと理解できたはずです。

質問やフィードバックがあれば、下のコメント欄からお気軽にお寄せください。

最後までお読みいただき、ありがとうございました!

  1. 【開発者向け】iOS 12ベータ版のインストール方法を徹底解説

    WWDC 2018は、数々の驚きと新発表に満ちたイベントとなりました。中でも最も注目を集めたのが、iOS 12への大型アップデートです。iOS 12では、Memoji(ミーモジ)、ARKit 2、Animoji、Siriショートカット、グループFaceTimeなど、魅力的な新機能が多数搭載されています。 現在、iOS 12は開発者向けに公開されています。「正式リリースを待ちきれない」「ベータ版でも問題ない」という方は、ぜひ本記事をご覧ください。この記事では、iOS 12ベータ版のダウンロードとインストールの手順を詳しく解説します。 注意: ベータ版にはバグが含まれており、改善の余地も多く残って

  2. Windows 10 を無料でダウンロード・アップグレードする方法【完全解説】

    Microsoftは1年以上前にWindows 7のサポートを終了し、デバイスを安全かつ快適に動作させ続けるために、最新のWindows 10へのアップグレードを推奨しています。これは、Windows 7に対するテクニカルサポート、セキュリティ更新プログラム、バグ修正が一切提供されなくなることを意味します。つまり、Windows 7を使い続けるのは安全とは言えず、今こそWindows 10に切り替える絶好のタイミングなのです。さらに、Windows 11は10月に展開される予定であり、無料アップグレードの対象はWindows 10ユーザーのみです。だからこそ、お使いのパソコンを今すぐアップグレ