Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Hiểu Rack: Xương sống của Ruby Web Framework

Đang xảy ra gì behind the scenes của mọi Rails, Sinatra, và Ruby web framework khác?

Câu trả lời là Rack, component then chốt làm cho điều này possible.

Nhưng Rack chính xác là gì?

Rack là layer giữa framework (Rails) và application server (Puma).

Hiểu Rack: Xương sống của Ruby Web Framework

Nó là chất keo cho phép chúng communicate.

Tại sao dùng Rack?

Chúng ta dùng Rack vì nó cho phép framework và server khác nhau interchangeable.

Chúng thành component plug-and-play.

Nghĩa là bạn dùng Puma với Rails, Sinatra và bất kỳ Rack-compatible framework nào. Không quan trọng framework hoặc server bạn dùng miễn chúng implement Rack interface.

Với Rack, mọi component làm việc của nó và mọi người happy!

Rack Middleware là gì?

Rack nằm giữa mọi web request và response.

Kết quả, nó act như guardian, deny access unwanted request, hoặc historian, track slow response.

Đó là Rack middleware!

Nhỏ Ruby program được gọi như phần của request-response cycle và có chance làm gì đó với nó.

Dùng cho gì?

  • Logging
  • Sessions
  • Profiling (tìm request mất bao lâu complete)
  • Caching
  • Security (deny request dựa trên IP, hoặc limit # request)
  • Serving static files (css, js, png…)

Đây khá useful và Rails dùng middleware tốt để implement một số functionality.

Bạn xem list middleware với rake middleware trong project Rails.

Bây giờ, Rack interface** tôi nói trước.

Trông như thế nào?

Cho bạn xem ví dụ…

Cách viết Rack Application riêng

Bạn học Rack hoạt động như nào bằng cách viết app riêng.

Làm nào!

Rack application là class với một method: call.

Trông như sau:

 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 

Code này start server port 8080 (thử đi!).

Array trả về là gì?

  • HTTP status code (200)
  • HTTP headers ("Content-Type")
  • Nội dung ("Hello from Rack")

Nếu muốn truy cập request detail dùng argument env.

Như sau:

 req = Rack::Request.new(env) 

Các method available:

  • path_info (/articles/1)
  • ip (của user)
  • user_agent (Chrome, Firefox, Safari…)
  • request_method (get / post)
  • body (nội dung)
  • media_type (plain, json, html)

Bạn dùng info này xây dựng Rack application.

Ví dụ, deny access content nếu IP là 5.5.5.5.

Code:

 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 

Bạn đổi address thành 127.0.0.1 xem effect.

Nếu không work thử ::1, IPv6 localhost.

Cách viết & dùng Rack Middleware

Bây giờ:

Làm sao chain application và middleware làm việc cùng nhau?

Dùng Rack::Builder.

Cách hiểu tốt nhất là ví dụ.

Rack app của chúng ta:

 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 

Middleware:

 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 

Cách combine:

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

Trong ví dụ này có hai Rack application:

  • Một cho IP check (FilterLocalHost)
  • Một cho app deliver content (HTML, JSON, etc)

Chú ý @app.call(env), đó là điều làm FilterLocalHost thành middleware.

Một trong hai chuyện xảy ra:

  • Trả response, stop middleware chain
  • Pass request với @app.call(env) cho middleware tiếp, hoặc app

Bất kỳ phần nào Rack app, kể cả middleware, bạn thay đổi response.

Ví dụ:

 class UpcaseAll
  def initialize(app)
    @app = app
  end
  def call(env)
    status, headers, response = @app.call(env)
    response.upcase!
    [status, headers, response]
  end
end 

Đó chính là cách Rack hoạt động 🙂

Tóm tắt

Bạn đã học về Rack, interface điều khiển tương tác giữa Ruby web framework và server. Cũng học viết Rack app riêng để hiểu cách hoạt động.

Nếu có câu hỏi hoặc feedback hãy comment bên dưới.

Cảm ơn đã đọc!