Tìm hiểu về Ruby Rack
Nếu đã từng lập trình web với Ruby, bạn đã làm việc với Rack. Có thể nói Rack chính là nền tảng cho các web framework của Ruby như Sinatra, Rails hay Lotus,... Rack cung cấp một minimal, modular, and adaptable interface để phát triển các ứng dụng web trong Ruby. Bằng cách gói các HTTP request và ...
Nếu đã từng lập trình web với Ruby, bạn đã làm việc với Rack. Có thể nói Rack chính là nền tảng cho các web framework của Ruby như Sinatra, Rails hay Lotus,...
Rack cung cấp một minimal, modular, and adaptable interface để phát triển các ứng dụng web trong Ruby. Bằng cách gói các HTTP request và respone theo cách đơn giản nhất, nó hợp nhất và chọn lọc các API cho các web server, web framework và phần mềm trung gian(được gọi là middleware) vào một phương thức đơn là call
Tìm hiểu về Rack giúp ta có hiểu được cách thức hoạt động của các web framework, từ đó tùy biến chúng dễ dàng hơn.
Rack là gì?
Rack là:
- a web server interface.
- a protocol for buiiding and composing web applications.
- a collection of middleware utilities.
Setup rack
Gem của Rack có sẵn tại rubygems.org, chúng ta có thể cài đặt như sau:
gem install rack
A Web Server Interface:
Rack cung cấp một cách chuẩn để ứng dụng Ruby giao tiếp được với web server. Tức là, Rack cung cấp một giao tiếp giữa các máy chủ Web hỗ trợ Ruby (Unicorn, Puma, Phusion Passenger, WEBrick,Thin,…) với các Ruby framework(Rails, Sinatra, Lotus, …).
The Protocol:
Một Rack application có cấu trúc rất đơn giản: nó là một Ruby Object, định nghĩa call method. call method có tham số đầu vào là một biến environment và trả về response với response là một array có 3 item [status, headers, body]:
- status: is the HTTP status code.
- headers: is a hash of HTTP headers for the response.
- body: is the actual body of the response (e.g. the HTML you want to display). The body must also respond to each.
Một ví dụ đơn giản như sau:
Cách 1: Cách này sau khi code bạn cần phải start lại server.
# rack_app.rb require 'rack' app = Proc.new do |env| ['200', {'Content-Type' => 'text/html'}, ['Welcome to ruby rack!']] end Rack::Handler::WEBrick.run app
Cách 2: Tạo file config.ru có nội dung:
# config.ru run Proc.new { |env| ['200', {'Content-Type' => 'text/html'}, ['Welcome to ruby rack!']] }
Sau đó, mở terminal và chạy lệnh rackup như sau:
rackup config.ru
Hoặc
# config.ru clasacks HelloRack def self.call(env) [200, {"Content-Type" => "text/plain"}, ["Welcome to ruby rack!"] ] end end run HelloRack
Ở terminal, chỉ cần chạy lệnh
rackup Listening on localhost:9292, CTRL+C to stop 127.0.0.1 - - [25/Jun/2016:03:28:56 +0700] "GET / HTTP/1.1" 200 - 0.0012 127.0.0.1 - - [25/Jun/2016:03:29:07 +0700] "GET / HTTP/1.1" 200 - 0.0012
Giải thích hoạt động của ứng dụng trên:
Ứng dụng này làm một nhiệm vụ rất đơn giản, với tất cả các request, trả về respose là đoạn text “Welcome to ruby rack!”, cùng với response code 200. Khi rackup ở trên, mặc định Rack sẽ dùng web server có sẵn của Ruby là WEBrick làm web server. WEBrick sẽ lắng nghe ở cổng 9292. Khi dùng browser access vào địa chỉ: http://localhost:9292 ta sẽ thấy nội dung trả về là dòng text: “Welcome to ruby rack!"
Khi WEBrick nhận request từ browser, nó sẽ gọi hàm call của class HelloRack mà ta viết ở trên, truyền vào biến env, lấy nội dung trả về của hàm này để trả về cho browser.
Middleware:
Middleware cung cấp cho bạn một cách để tạo các ứng dụng rack với nhau. Một middleware chỉ đơn giản là Rack appliaction được khởi tạo với một Rack application khác. Ta có thể định nghĩa những middleware khác nhau làm những việc khác nhau và sau đó có thể xếp chúng cùng nhau và cùng thực hiện một việc hữu ích khác.
Giữa server và framework, Rack tùy chỉnh ứng dụng theo middleware, một số middleware như sau: Rack::URLMap, to route to multiple applications inside the same process.
- Rack::CommonLogger, for creating Apache-style logfiles.
- Rack::ShowException, for catching unhandled exceptions and presenting them in a nice and helpful way with clickable backtrace.
- Rack::File, for serving static files.
... và còn rất nhiều middleware khác.
Khi bạn có 1 ứng dụng Rails, bạn có thể mở terminal lên để kiểm tra những middleware mà ứng dụng đó đang sử dụng bằng lệnh rake middleware như sau:
$my_app rake middleware use Rack::Sendfile use ActionDispatch::Static use Rack::Lock use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000004e6d5f8> use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use ActionDispatch::RemoteIp use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActiveRecord::Migration::CheckPending use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore use ActionDispatch::Flash use ActionDispatch::ParamsParser use Rack::Head use Rack::ConditionalGet use Rack::ETag use Warden::Manager use OmniAuth::Strategies::Facebook use OmniAuth::Strategies::Google run MyApp::Application.routes
Ví dụ về sử dụng middleware như sau:
class ToUpper def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) upcased_body = body.map { |chunk| chunk.upcase } [status, headers, upcased_body] end end class Hello def self.call(env) [ 200, {"Content-Type" => "text/plain"}, ["Hello from Rack!"] ] end end use ToUpper run Hello
Như vậy với khả năng mở rộng của Rails bạn có thể dễ dàng thêm những middleware custom phù hợp với mục đích sử dụng. Hi vọng, qua bài viết này các bạn sẽ có thêm kiến thức với Rack và Rack Middleware.
Tham khảo:
https://github.com/rack/rack
http://www.rubydoc.info/github/rack/rack
http://code.tutsplus.com/tutorials/exploring-rack--net-32976