Tìm hiểu Ruby Rack
1. Giới thiệu Rack provides a minimal interface between webservers that support Ruby and Ruby frameworks. Rack là interface giúp web server và web framework giao tiếp với nhau. Webserver ở đây có thể là WEBrick, Thin, Unicorn, Puma, và web framework có thể là Rails, Sinatra, … 2. ...
1. Giới thiệu
Rack provides a minimal interface between webservers that support Ruby and Ruby frameworks.
Rack là interface giúp web server và web framework giao tiếp với nhau. Webserver ở đây có thể là WEBrick, Thin, Unicorn, Puma, và web framework có thể là Rails, Sinatra, …
2. Cấu trúc ứng dụng Rack
Rack application đơn giản là một Ruby Object, định nghĩa một hàm có tham số là một biến environment và trả về response. Response là một array có 3 item:
- HTTP response code
- Header
- Body của response
Ta thử viết một ứng dụng Rack đơn giản:
Tạo file simplerack.rb:
# simplerack.rb require 'rack' app = Proc.new do |env| ['200', {'Content-Type' => 'text/html'}, [env.inspect]] end Rack::Handler::WEBrick.run app
Hoặc, tạo file config.ru:
# config.ru run Proc.new { |env| ['200', {'Content-Type' => 'text/html'}, ['get rack'd']] }
Nếu chưa cài gem rack:
$ gem install rack
Chạy ứng dụng:
$ ruby simple_rack.rb
Hoặc,
$ rackup config.ru
Kết quả:
[2016-05-24 20:35:41] INFO WEBrick 1.3.1 [2016-05-24 20:35:41] INFO ruby 2.1.2 (2014-05-08) [x86_64-linux] [2016-05-24 20:35:41] INFO WEBrick::HTTPServer#start: pid=21808 port=8080
Giải thích
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 (ở đây ta hoàn toàn có thể config để dùng các web server khác). Khi WEBrick nhận request từ browser, nó sẽ lấy nội dung trả về của Proc ta định nghĩa trong file trên để trả về cho browser.
WEBrick sẽ lắng nghe ở cổng 8080. Trong ví dụ trên, khi dùng browser access vào địa chỉ: http://localhost:8080 ta sẽ thấy nội dung trả về là nội dung biến env cùng với response code 200: Trong đó có một số key cần chú ý:
- PATH_INFO: path của request. Mặc định sẽ là /
- QUERY_STRING: params của request
- REQUEST_METHOD: http method, GET, POST,…
Thử access bằng địa chỉ: http://localhost:8080/index.php?id=1010 ta sẽ thấy các value tương ứng với các key trên:
- PATH_INFO: /index.php
- QUERY_STRING: id=1010
- REQUEST_METHOD: GET
3. Rack middleware
Ta có thể nối nhiều Rack application lại với nhau bằng Rack middle, ouput của Rack application sẽ là input của application khác. Việc này cung cấp tính mềm déo cho ứng dụng Rack, ta có thể thêm hoặc bớt các middleware theo ý mình mà không sợ ảnh hưởng đến middleware có sẵn.
Ví dụ điển hình nhất chính là Rails. Rails là một Rack application được tạo thành bởi nhiều Rack middleware. Chẳng hạn:
Rails::Rack::Logger ActiveRecord::QueryCache ActionDispatch::Cookies ActionDispatch::Session::CookieStore ActionDispatch::ParamsParser Rails.application.routes
Để hiểu rõ hơn, ta viết ứng dụng SimpleRack với 2 middleware như sau:
# middleware.ru class Logger def initialize @app = app end def call(env) status, header, body = @app.call(env) body.unshift("Info: This is log of Logger middleware ") [status, header, body] end end class SimpleRack def self.call(env) [200, {"Content-Type" => "text/plain"}, ["Hello from Rack!"] ] end end use Logger run SimpleRack
Thứ tự thực hiện của ứng dụng Rack trên như sau:
Request --> WEBrick --> Logger --> SimpleRack --> Logger --> Browser
Logger sẽ pass request cho SimpleRack xử lý, SimpleRack xử lý xong trả response lại cho Logger, Logger append một dòng log vào response và trả response này về lại cho browser
Vì thế khi access địa chỉ http://localhost:8080 ta thấy ngoài nội dung “Hello from Rack!” còn thêm 1 dòng “Info: This is log of Logger middleware”, dòng này chính là kết quả việc thực hiện middleware Logger.
Bên cạnh các chức năng cơ bản trên, Rack còn implement sẵn một số hàm helper như parse params, build response,… Chi tiết hơn có thể tham khảo ở document của Rack tại: http://www.rubydoc.info/github/rack/rack hoặc http://rack.github.io/
Nguồn: http://hawkins.io/2012/07/rack_from_the_beginning/