Middleware Rack là một object có call(env) trả về mảng [status, headers, body], và giữ tham chiếu tới middleware kế tiếp (@app).
ruby
# lib/middleware/request_timer.rb
class RequestTimer
def initialize(app)
@app = app
end
def call(env)
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
status, headers, body = @app.call(env) # pass down the stack
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - started
headers['X-Runtime-Custom'] = elapsed.round(4).to_s
[status, headers, body]
end
endĐăng ký trong config/application.rb:
ruby
config.middleware.use RequestTimer # append to the end
config.middleware.insert_before Rack::Runtime, RequestTimer
config.middleware.insert_after ActionDispatch::Static, RequestTimerVị trí quan trọng: đặt càng gần đầu stack thì càng đo được nhiều (kể cả thời gian của các middleware khác), nhưng lúc đó session và params chưa được parse. Nếu middleware cần đọc session hay current_user thì phải chèn sau ActionDispatch::Session::CookieStore. Xem stack thật bằng bin/rails middleware.
Dùng middleware cho việc cắt ngang mọi request không cần biết route: rate limit theo IP, health check, đo thời gian, chặn host lạ. Việc phụ thuộc controller/route thì dùng before_action chứ không dùng middleware.