Điều gì đang xảy ra đằng sau hậu trường của mọi khung công tác web Rails, Sinatra và Ruby khác?
Câu trả lời là Rack, thành phần quan trọng làm nên điều này.
Nhưng chính xác thì Rack là gì?
Rack là một lớp giữa khung công tác (Rails) và máy chủ ứng dụng (Puma).
Đó là chất keo cho phép họ giao tiếp.
Tại sao chúng tôi sử dụng Rack?
Chúng tôi sử dụng Rack vì điều đó cho phép các khung và máy chủ khác nhau có thể hoán đổi cho nhau.
Chúng trở thành thành phần mà bạn có thể plug-in .
Điều này có nghĩa là bạn có thể sử dụng Puma với Rails, Sinatra và bất kỳ framework nào khác tương thích với Rack. Không quan trọng bạn đang sử dụng khung hoặc máy chủ nào nếu chúng triển khai giao diện Rack .
Với Rack, mọi thành phần đều thực hiện công việc của mình và mọi người đều vui vẻ!
Phần mềm trung gian Rack là gì?
Rack nằm ở giữa mọi yêu cầu và phản hồi trên web.
Do đó, nó có thể hoạt động như một người giám hộ, bằng cách từ chối quyền truy cập vào các yêu cầu không mong muốn hoặc nó có thể hoạt động như một nhà sử học, bằng cách theo dõi các phản hồi chậm.
Đó là những gì Phần mềm trung gian của Rack là!
Các chương trình Ruby nhỏ được gọi như một phần của chu trình yêu cầu-phản hồi và có cơ hội làm điều gì đó với nó.
Loại này được sử dụng để làm gì?
- Ghi nhật ký
- Phiên
- Lập hồ sơ (tìm hiểu xem yêu cầu mất bao lâu để hoàn thành)
- Bộ nhớ đệm
- Bảo mật (từ chối các yêu cầu dựa trên địa chỉ IP hoặc giới hạn số lượng yêu cầu)
- Cung cấp các tệp tĩnh (css, js, png…)
Đây là những thứ khá hữu ích & Rails tận dụng tốt phần mềm trung gian để triển khai một số chức năng của nó .
Bạn có thể xem danh sách phần mềm trung gian với rake middleware
bên trong một dự án Rails.
Bây giờ, Giao diện giá đỡ này Tôi đã đề cập trước đó.
Nó trông như thế nào?
Để tôi cho bạn xem một ví dụ…
Cách viết ứng dụng giá đỡ của riêng bạn
Bạn có thể tìm hiểu cách Rack hoạt động bằng cách viết ứng dụng của riêng bạn.
Hãy làm điều này!
Ứng dụng Rack là một lớp có một phương thức:call
.
Có vẻ như thế này :
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
Mã này sẽ khởi động máy chủ trên cổng 8080 ( hãy thử! ).
Mảng này đang được trả về là gì?
- Mã trạng thái HTTP (200)
- Tiêu đề HTTP (“Loại nội dung”)
- Nội dung (“Xin chào từ Rack”)
Nếu bạn muốn truy cập chi tiết yêu cầu, bạn có thể sử dụng env
đối số.
Như thế này :
req = Rack::Request.new(env)
Các phương pháp này có sẵn :
- path_info (/ posts / 1)
- ip (của người dùng)
- user_agent (Chrome, Firefox, Safari…)
- request_method (get / post)
- nội dung (nội dung)
- media_type (trơn, json, html)
Bạn có thể sử dụng thông tin này để xây dựng ứng dụng Rack của mình .
Ví dụ:chúng tôi có thể từ chối quyền truy cập vào nội dung của mình nếu địa chỉ IP là 5.5.5.5
.
Đây là mã :
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 có thể thay đổi địa chỉ thành 127.0.0.1
nếu bạn muốn thấy hiệu ứng.
Nếu cách đó không hiệu quả, hãy thử ::1
, phiên bản IPv6 của localhost.
Cách viết và sử dụng phần mềm trung gian của Rack
Bây giờ:
Làm cách nào để bạn liên kết ứng dụng và phần mềm trung gian để chúng hoạt động cùng nhau?
Sử dụng Rack::Builder
.
Cách tốt nhất để hiểu là với một ví dụ.
Đây là ứng dụng Rack của chúng tôi :
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
Đây là phần mềm trung gian :
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
Đây là cách chúng tôi kết hợp chúng với nhau :
app = Rack::Builder.new do |builder| builder.use FilterLocalHost builder.run RackApp.new end handler.run app
Trong ví dụ này, chúng tôi có hai ứng dụng Rack:
- Một để kiểm tra IP (
FilterLocalHost
) - Một cho chính ứng dụng để cung cấp nội dung (HTML, JSON, v.v.)
Lưu ý rằng @app.call(env)
, đó là điều tạo nên FilterLocalHost
một phần mềm trung gian.
Một trong hai điều có thể xảy ra :
- Chúng tôi trả lại một phản hồi, điều này sẽ dừng chuỗi phần mềm trung gian
- Chúng tôi chuyển yêu cầu cùng với
@app.call(env)
đến phần mềm trung gian tiếp theo hoặc chính ứng dụng
Bên trong bất kỳ phần nào của ứng dụng Rack, bao gồm cả phần mềm trung gian, bạn có thể thay đổi phản hồi.
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 xác là cách Rack hoạt động 🙂
Tóm tắt
Bạn đã tìm hiểu về Rack, giao diện thúc đẩy sự tương tác giữa các máy chủ và khuôn khổ web Ruby. Bạn cũng đã học cách viết ứng dụng Rack của riêng mình để hiểu cách nó hoạt động.
Nếu bạn có bất kỳ câu hỏi hoặc phản hồi nào, vui lòng để lại bình luận bên dưới.
Cảm ơn vì đã đọc!