Rails on Rack
Tiếp theo bài viết trước, trong bài này mình sẽ đi sâu vào phân tích ứng dụng của Rack với framework Rails.
Như chúng ta đã biết, Rails là một framework sử dụng Rack middleware. Một request để đến được controller, model, view đã qua xử lý của rất nhiều Rack Middleware. Theo document của Rails, mặc định, các Rack Middleware sau được sử dụng để xử lý request:
Để hiểu rõ hơn, ta thử phân tích một số Rack Middleware đơn giản.
Rack::Sendfile
Trước tiên một request sẽ qua middleware Rack::Sendfile
. Thực chất đây là một middleware được cung cấp sẵn trong thư viện Rack. Để biết được middleware này giữ nhiệm vụ gì, ta tham khảo source của Rack tại Github
Code của class Sendfile
khá ngắn nên không quá khó hiểu. Như trong bài viết trước, một ứng dụng rack middleware sẽ implement một hàm call
. Hàm này nhận vào biến env
và trả về mảng [status, headers, body]
. Trước tiên hàm call
của Sendfile
sẽ gọi:
Đây là lệnh gọi xử lý của các middleware phía sau. Sau khi các middleware khác đã được xử lý xong, SendFile
sẽ giữ nhiệm vụ lấy chuỗi to_path
từ biến body và trả về file tương ứng. Điều này được thể hiện trong đoạn code:
Tóm lại chức năng của middleware Sendfile là lấy chuỗi to_path
từ body
và append vào response header. Các web server bên dưới như nginx, apache khi nhận được response header này sẽ đọc file được chỉ ra ở đường dẫn to_path
và trả về cho client. Điều này giúp cho ứng dụng Rails app đỡ phải xử lý các tác vụ đọc file trong trường hợp kết quả trả về là nội dung của một file static.
ActionDispatch::Static
Code của class static tham khảo tại Github
Ta thấy chức năng của middleware này rất đơn giản, nếu biến request header có biến PATH_INFO
, middleware này sẽ đọc file được chỉ ra ở biến PATH_INFO
trong thư mục root(thông thường là thư mục public
) và trả về cho client. Nếu không tìm thấy file hoặc không có header PATH_INFO
request sẽ được forward đến các middleware phía sau để xử lý tiếp.
ActionDispatch::RequestId
Sau khi đi qua 2 middleware khác(Rack::Lock
và Cache
), đến lược class RequestId
được gọi. Github
Middleware này có giữ nhiệm vụ set header X-Request-Id
, header này được sinh ngẫu nhiên(sử dụng class SecureRandom
)
Như vậy ta thấy để đến được bước xử lý của code controller, model, view. Một request đã đi ra rất nhiều bước tiền xử lý. Ở danh sách các middleware mặc định ở trên, ta để ý thấy dòng cuối cùng:
Đây chính là lúc request đi vào xử lý routing của ứng dụng Rails. Lúc này request sẽ được đưa đến các controller, model, view tương ứng.
Thêm, xóa một middleware
Chính cấu trúc module của Rack middleware giúp ta dễ dàng thêm hoặc bớt một middleware bất kỳ. Chẳng hạn, muốn thêm một middleware ta config trong file application.rb
:
Hoặc để xóa một middleware có sẵn ta config như sau(cũng trong file application.rb
)
Để hiểu chi tiết hơn về các middleware khác, ta có thể tham khảo ở các địa chỉ sau: