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

シナトラがどのように機能するかのクイック分析

SinatraはRubyWebフレームワークです。

Railsの弟のようです…

シナトラのしくみを探りましょう

  • プロジェクトにシナトラが必要な場合はどうなりますか?
  • ルートマッチングはどのように機能しますか?
  • リクエストとレスポンスはどのように処理されますか?

質問はたくさんありますが、時間はほとんどありません…

問題ありません!

私はあなたのために一生懸命働いて、あなたがより速く学ぶことができるように私がこれらの質問に答えるこの記事をまとめました!

シナトラの初期化

すべては1つのファイルから始まります: sinatra.rb

このファイルが行うのは、 main.rbを要求することだけです。 、あまりエキサイティングではありませんか?

今ではもっと面白くなります!

main.rbの内部 base.rbの要件が見つかります &オプション解析のコード(ポート、環境、クワイエットモードなど)もあります。

Sinatraはoptparseを使用します 、Rubyの標準ライブラリから。

ここで他に何を見つけることができますか?

このat_exitをご覧ください ブロック:

at_exit { Application.run! if $!.nil? && Application.run? }

これは、プログラムの終了時に実行されるコードです。

何が起こるかというと、すべてのコードがRubyによって読み取られ、ループやスリープなどがないため、プログラムは自然に終了します。

…ただし、 at_exitが終了する直前 ブロックがトリガーされます!

次に、SinatraがWebサーバーを引き継いで起動し、リクエストを処理できるようにします。

これを行うコードは次のとおりです

begin
  start_server(handler, server_settings, handler_name, &block)
rescue Errno::EADDRINUSE
  $stderr.puts "== Someone is already performing on port #{port}!"
  raise
end

# Part of base.rb `run!` method

ああ、もう1つの重要なことがここで起こります:

extend Sinatra::Delegator

Sinatra ::Delegator getのようなSinatraDSLメソッドを定義するモジュールです。 、 post set

これができる理由です:

get '/' do
  puts "Hello World!"
end

Sinatraはグローバルなmainを拡張します このモジュールのオブジェクト。

要求と応答の処理

さて、この時点で、新しい接続を受け入れる準備ができている実行中のサーバーがあります。

しかし、新しい接続を受信するとどうなりますか?

Railsや他のRubyWebフレームワークと同様に、SinatraはRackを使用してすべての下位レベルのものを処理します。

ラックはcallを期待しています アプリケーションで使用できるメソッド。これは、初期化するときにRackに渡すオブジェクトにすぎません。

Sinatraの場合、このオブジェクトは Sinatra ::Baseです。 クラス。

方法は次のとおりです

# Rack call interface.

def call!(env)
  @env      = env
  @request  = Request.new(env)
  @response = Response.new

  invoke { dispatch! }
  invoke { error_block!(response.status) } unless @env['sinatra.error']

  @response.finish
end

# Modified version of Sinatra's call method (for clarity)

発送を調査する必要があるようです! リクエストの処理方法を示す次のメソッド。

その方法は次のとおりです

def dispatch!
  invoke do
    static! if settings.static? && (request.get? || request.head?)
    filter! :before
    route!
  end
rescue ::Exception => boom
  invoke { handle_exception!(boom) }
ensure
  filter! :after unless env['sinatra.static_file']
end

# Edited down to the important parts

リクエストは4つのステップに分かれています

  1. 静的ファイルが最初にチェックされます。これらは、css、js、imagesなどのファイルです。 「public」という名前のディレクトリが存在する場合、この設定はデフォルトで有効になっています
  2. ビフォーフィルターが実行されます
  3. ルートマッチング
  4. アフターフィルターが実行されます

これで、各ステップを掘り下げて、何が起こるかをより詳細に確認できます。

静的ファイルの提供

static! 方法はとても簡単です:

def static!(options = {})
  return if (public_dir = settings.public_folder).nil?
  path = File.expand_path("#{public_dir}#{URI_INSTANCE.unescape(request.path_info)}" )
  return unless File.file?(path)

  cache_control(*settings.static_cache_control) if settings.static_cache_control?
  send_file(path, options)
end

このコードは、要求されたファイルが存在するかどうかを確認し、「キャッシュ制御」HTTPヘッダーを設定します。

最後の行で、 send_fileを呼び出します。 &それは名前が言うことを正確に行います🙂

フィルター前

beforeフィルターを使用すると、一致するルートを見つける前にコードを実行できます。

フィルタを追加する方法は次のとおりです。

# Define a before filter.

# Runs before all requests within the same context as route handlers
# and may access/modify the request and response.

@filters = {:before => [], :after => []}

def before(path = /.*/, **options, &block)
  add_filter(:before, path, options, &block)
end

def after(path = /.*/, **options, &block)
  add_filter(:after, path, options, &block)
end

def add_filter(type, path = /.*/, **options, &block)
  filters[type] << compile!(type, path, block, options)
end

ご覧のとおり、 filters フィルタタイプごとに1つずつ、2つのキーを持つ単なるハッシュです。

しかし、 compile!とは何ですか ?

このメソッドは、パターン、条件の配列、ラッパーの3つの要素を持つ配列を返します。

ルートの生成にも同じ方法が使用されます( get を使用する場合) またはpost ブロック):

def get(path, opts = {}, &block)
  route('GET', path, opts, &block)
end

def route(verb, path, options = {}, &block)
  signature = compile!(verb, path, block, options)

  (@routes[verb] ||= []) << signature

  signature
end

# Methods edited for clarity

このことから、シナトラフィルターがルートと同じように動作および機能することがわかります。

ルートマッチング

リクエスト処理サイクルの次のステップはルートマッチングです:

def route!(base = settings, pass_block = nil)
  routes = base.routes[@request.request_method]

  routes.each do |pattern, conditions, block|
    process_route(pattern, conditions)
    route_eval
  end

  route_missing
end

# Edited method

このコードは、リクエストメソッド( get )に一致するすべてのルートを通過します 、 post など)。

ルートマッチングはprocess_route内で行われます 方法:

def process_route(pattern, keys, conditions, block = nil, values = [])
  route = @request.path_info
  route = '/' if route.empty? and not settings.empty_path_info?

  return unless match = pattern.match(route)
end
でない限り戻る

ここでpattern は正規表現です。

ルートがパスと条件の両方に一致する場合は、 route_eval ブロック( get の本体)を評価するが呼び出されます /投稿 route)&ルートマッチングプロセスを終了します。

# Run a route block and throw :halt with the result.
def route_eval
  throw :halt, yield
end

これは珍しいcatchを使用します /投げる フロー制御のメカニズム。

コードの流れをたどるのは非常に混乱する可能性があるため、これには反対することをお勧めしますが、この機能の実際の使用例を見るのは興味深いことです。

レスポンスビルディング

リクエストサイクルの最後のステップは、レスポンスを準備することです。

では、応答はどこに行きますか?

invoke メソッドは次のように応答を収集します:

res = catch(:halt) { yield }

この結果は、 bodyを使用して応答本文に割り当てられます。 方法:

body(res)

ここで、開始した場所を振り返ると、 call メソッドの場合、次のコード行が見つかります:

@response.finish

これはfinishを呼び出します @responseのメソッド 、これは Rack ::Responseです オブジェクト。

つまり、これにより実際に応答がトリガーされてクライアントに送信されます。

ボーナス:Setメソッドのしくみ

setメソッドはSinatraのDSL(ドメイン固有言語)の一部であり、Sinatraアプリケーションの任意の場所に構成オプションを設定できます。

set :public_folder, '/var/www'

setを使用するたびに Sinatraは(メタプログラミングを介して)3つのメソッドを作成します:

define_singleton("#{option}=", setter) if setter
define_singleton(option, getter)       if getter
define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"

3つのメソッドは( public_folder を使用)です 例として):

  • public_folder
  • public_folder =
  • public_folder?

このメソッドは、setterメソッド( public_folder =)も呼び出します。 )すでに存在する場合:

if respond_to?("#{option}=") && !ignore_setter
  return __send__("#{option}=", value)
end

メタプログラミングは無料ではないので、 optionsを使い続けることを忘れないでください ハッシュ。これらの凝った方法は必要ありません。

概要

Sinatraが初期化される方法、要求を処理する方法、および応答が生成されるまでに実行するさまざまな手順について学習しました。これは、いくつかのRubyのトリックを学び、シナトラをよりよく理解するのに役立ちます!

この投稿を共有することを忘れないでください 他のRuby開発者と一緒に、彼らもそこから学ぶことができます🙂


  1. Excel にデータ分析をインストールする方法

    Microsoft Excel は、さまざまな種類のデータ分析に非常に広く使用されています。複雑な統計的または工学的分析を開発したい場合、時間と労力がかかります。しかし、Excel のデータ分析オプションを使用することで、問題を根絶することができます。 しかし、その機能を自然に使うことはできません。最初にインストールする必要があります。この記事では、Excel にデータ分析をインストールする方法を示します。 データ分析ツールパックとは データ分析ツールパック アドインです データ分析を有効にするために不可欠な Excel で . Data Analysis Toolpak をインストールする

  2. エンドポイント セキュリティとは?エンドポイント セキュリティの仕組み

    エンドポイント セキュリティは、さまざまなセキュリティ アクションを包含する広大な用語ですが、最も一般的にはネットワーク セキュリティに関連付けられています。エンドポイント セキュリティとしてより一般的に知られているエンドポイント プロテクションは、企業のネットワークをワイヤレス、リモート、またはタブレット、ラップトップ、スマートフォンなどのモバイル ガジェットで保護する方法です。 2018 年には約 1 億件のサイバー侵害が報告されており、サイバーセキュリティは見逃すにはあまりにも重要です。 EndPoint の世界でエキサイティングな旅を始めて、EndPoint について知っておくべきこと