<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • Rack相關知識梳理(一)

    一、什么是Rack
    Rack是ruby應用服務器和Rack應用程序之間的接口,
    這里面Ruby應用服務器可以是Webrick、thin等,Rack應用程序可以是rails、Sinatra等(其實 現在主流的ruby的Web框架都是基于Rack的)。在上圖中,當用戶的請求到達應用服務器時,應用服務器會調用rack對請求進行包裝,然后在 調用你的rack應用程序,rack程序可以對請求進行分析、處理,并利用rack的響應設施進行輸出,rack會將用戶響應作為輸出返回給ruby應用服務器。

     

    二、為什么要用Rack

    1、提供一個廣泛支持的標準接口

    Rack提供了一個標準接口,便于應用程序和應用服務器進行交互,一個Rack應用可以被任何和Rack兼容的應用服務器調用,最明顯的一個例子,我們開發的rails應用或者Sinatra應用可以直接使用Webrick或者thin等服務器啟動,不用做什么修改,非常方便。

    2、模塊化、高可重用性

    Rack利用中間件實現最大程度模塊化,從而提高Web應用程序部件的可重用性,從而提高開發效率

    Rack中間件對Ruby Web框架也有很深遠的影響:

    • 不同Web框架之間可重用Rack中間件,這意味著你編寫的中間件可以在所有主流框架中 使用;
    • 可以通過不同中間件的組合組裝出同一Web框架的不同變種以適應不同的需求;
    • 可以組合不同Web框架為同一個更大的系統服務。

    3、簡單

    Rack標準簡單,這就很容易讓用戶實現一個Web服務器或者Web框架

     

    三、一個簡單的Rack應用程序
    1、Rack嘗鮮

    一個Rack程序應該符合如下條件:

    • 是一個ruby對象,且具有call方法;
    • 只攜帶一個參數environment;
    • 返回值為一個數組,包含status、header、body三個元素。
    require 'rack'
    class MyApp 
      def call(env)
        [200, {}, ["this is my app"]] 
      end
    end
    my_app = MyApp.new
    Rack::Handler::WEBrick.run my_app, :Port => 3000

    運行這段代碼,在瀏覽器中訪問 http://localhost:3000

    上面這段代碼就是我們實現的一個最簡單的Rack應用,我們實現了一個類MyApp,他只有一 個call方法,此方法接受一個參數,返回一個數組,此數據包含status、header、body,在這 里呢,我使用WEBrick來啟動這個應用,同樣我也可以使用thin來啟動,那么最后一句話就變成:

    Rack::Handler::thin.run my_app, :Port => 3000

    我們在前面說了,目前主流的ruby應用服務器都是兼容Rack接口的,其實這里呢Rack使用了 一種叫Handler(句柄)的機制來實現對眾多應用服務器的支持,這些句柄都是在 Rack::Handler命名空間下的,我們可以看到這些類: 

    Rack::Handler::CGI
    Rack::Handler::FastCGI
    Rack::Handler::Mongrel
    Rack::Handler::EventedMongrel
    Rack::Handler::SwiftipliedMongrel
    Rack::Handler::WEBrick
    Rack::Handler::LSWS
    Rack::Handler::SCGI
    Rack::Handler::Thin

    也就是說Rack缺省下對上面這些服務器支持的。

    2、Rack的環境

    繼續回到我們剛才的應用中來,剛才代碼中我們call方法接受一個參數env,那么這個env到底有什么東?呢,我們修改下之前的代碼: 

    require 'rack'
    class MyApp
      def call(env)
        body = get_env(env)
        [200, {"Content-type" => "text/html"}, [body]]
      end
    
      def get_env(env) 
        env.map {|k, v| "#{k} => #{v}" }.sort.join("<br/>")
      end 
    end
    
    my_app = MyApp.new
    Rack::Handler::WEBrick.run my_app, :Port => 3000

    這段代碼中我們將env的值放到body中,在瀏覽器中訪問http://localhost:3000我們可以看到如下內容: 

    GATEWAY_INTERFACE => CGI/1.1
    HTTP_ACCEPT => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 HTTP_ACCEPT_ENCODING => gzip, deflate, sdch
    HTTP_ACCEPT_LANGUAGE => zh-CN,zh;q=0.8
    HTTP_CACHE_CONTROL => max-age=0
    HTTP_CONNECTION => keep-alive
    HTTP_COOKIE => remember_token=3E02V5zkb8eAmrUKckE69A
    HTTP_HOST => localhost:3000
    HTTP_UPGRADE_INSECURE_REQUESTS => 1
    HTTP_USER_AGENT => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36 HTTP_VERSION => HTTP/1.1
    PATH_INFO => /
    QUERY_STRING =>
    REMOTE_ADDR => ::1
    REMOTE_HOST => localhost
    REQUEST_METHOD => GET
    REQUEST_PATH => /
    REQUEST_URI => http://localhost:3000/
    SCRIPT_NAME =>
    SERVER_NAME => localhost
    SERVER_PORT => 3000
    SERVER_PROTOCOL => HTTP/1.1
    SERVER_SOFTWARE => WEBrick/1.3.1 (Ruby/2.0.0/2015-02-25)
    rack.errors => #
    rack.hijack => #<proc:0x007f843a9054a0@ users=”” yangye=”” .rvm=”” gems=”” ruby- 2.0.0-p643=”” rack-1.6.4=”” lib=”” rack=”” handler=”” webrick.rb:76=”” (lambda)=””> rack.hijack? => true
    rack.hijack_io =>
    rack.input => # rack.multiprocess => false rack.multithread => true rack.run_once => false rack.url_scheme => http rack.version => [1, 3]

    我們可以看出來,env的key主要包含大寫的CGI的頭,以及rack自己的環境變量 修改我們的url,我們可以看到返回的env中的一些鍵值會有不同的變化,各位自己嘗試下

    從上面我們可以看出來,我們編寫一個rack應用程序,可以通過env獲取用戶的請求的方法, 路徑名,查詢參數,從而調用不同的應用程序去處理,非常高效的去實現各種各樣的應用,但 是如果直接存取環境參數會很麻煩,我們還得自己去解析查詢參數,維護用戶會話信息,不過 好在rack本身提供了豐富的API幫我們解決了這些問題,下面來看兩個重要的類Request和 Response。

    3、常用的類

    Request

    這個類的定義是在rack-1.6.4/lib/rack/request.rb 我們要創建一個Request對象很簡單,只需要將env傳給其構造函數即可 Rack::Request.new(env) 不難想象,Request里面的諸多方法其實就是對env的解析,感興趣可以去閱讀下源碼 Response

    這個類的定義是在/rack-1.6.4/lib/rack/response.rb。

    創建一個Response對象也很簡單:Rack::Response.new

    這個類的構造函數如下: 

    def initialize(body=[], status=200, header={}) 
      @status = status.to_i
      @header = Utils::HeaderHash.new.merge(header)
      @chunked = CHUNKED == @header[TRANSFER_ENCODING] 
      @writer = lambda { |x| @body << x }
      @block = nil
      @length = 0
      @body = []
      if body.respond_to? :to_str 
        write body.to_str
      elsif body.respond_to?(:each) 
        body.each { |part| write part.to_s }
      else
        raise TypeError, "stringable or iterable required"
      end
      yield self if block_given? 
    end

    也就是說,我們在實例化對象時也可以直接傳遞status、header、body或者我們先實例化對象然后在修改這三個屬性。

     

     
    posted @ 2022-05-11 23:51  阿拉懶神燈  閱讀(39)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看