Rack middleware là gì?


267

Rack middleware trong Ruby là gì? Tôi không thể tìm thấy bất kỳ lời giải thích tốt cho những gì họ có nghĩa là "phần mềm trung gian".


4
Ngoài ra còn có một hướng dẫn trên RailsGuide hiện bao quát Rack một cách toàn diện, bao gồm cả phần mềm trung gian: guide.rubyonrails.org/rails_on_rack.html
xji

Cảm ơn rất nhiều đến nhóm PhusionPasbah, họ có một bài viết được giải thích rõ trên blog của họ. rubyraptor.org/ từ
Lamian

Giá đỡ và giá trung gian được giải thích trong bài viết NÀY . Cũng giải thích về việc tạo ra một ứng dụng dựa trên giá đỡ.
shashwat srivastava

Câu trả lời:


353

Giá như thiết kế

Phần mềm trung gian của Rack không chỉ là "cách lọc yêu cầu và phản hồi" - đó là cách triển khai mẫu thiết kế đường ống cho các máy chủ web sử dụng Rack .

Nó rất rõ ràng tách ra các giai đoạn khác nhau để xử lý một yêu cầu - tách các mối quan tâm là mục tiêu chính của tất cả các sản phẩm phần mềm được thiết kế tốt.

Ví dụ với Rack tôi có thể có các giai đoạn riêng biệt của đường ống đang thực hiện:

  • Xác thực : khi yêu cầu đến, các chi tiết đăng nhập của người dùng có chính xác không? Làm cách nào để xác thực OAuth, Xác thực cơ bản HTTP, tên / mật khẩu này?

  • Ủy quyền : "người dùng có được phép thực hiện tác vụ cụ thể này không?", Tức là bảo mật dựa trên vai trò.

  • Bộ nhớ đệm : Tôi đã xử lý yêu cầu này rồi, tôi có thể trả lại kết quả đã lưu không?

  • Trang trí : làm thế nào tôi có thể tăng cường yêu cầu để làm cho xử lý hạ nguồn tốt hơn?

  • Giám sát hiệu suất và sử dụng : tôi có thể nhận được số liệu thống kê nào từ yêu cầu và phản hồi?

  • Thực thi : thực sự xử lý yêu cầu và cung cấp một phản hồi.

Có thể tách các giai đoạn khác nhau (và tùy ý bao gồm chúng) là một trợ giúp tuyệt vời trong việc phát triển các ứng dụng có cấu trúc tốt.

cộng đồng

Ngoài ra còn có một hệ sinh thái tuyệt vời phát triển xung quanh Rack Middleware - bạn sẽ có thể tìm thấy các thành phần giá đỡ được xây dựng sẵn để thực hiện tất cả các bước trên và hơn thế nữa. Xem wiki Rack GitHub để biết danh sách các phần mềm trung gian .

Middleware là gì?

Middleware là một thuật ngữ khủng khiếp dùng để chỉ bất kỳ thành phần / thư viện phần mềm nào hỗ trợ nhưng không liên quan trực tiếp đến việc thực hiện một số tác vụ. Các ví dụ rất phổ biến là ghi nhật ký, xác thực và các thành phần xử lý ngang phổ biến khác . Đây có thể là những thứ mà mọi người cần trên nhiều ứng dụng nhưng không có quá nhiều người quan tâm (hoặc nên có) trong việc xây dựng bản thân.

Thêm thông tin


Một điều tôi không rõ ràng: tất cả các phần mềm trung gian có chia sẻ cùng một dữ liệu không? Có thể tách chúng (tức là hộp cát một) để bảo mật không?
Brian Armstrong

2
Rack là một phần của ứng dụng của bạn, vì vậy tất cả các bộ phần mềm trung gian đều có cùng một bản sao của yêu cầu và mỗi bộ có thể sửa đổi nó theo bất kỳ cách nào chúng muốn. AFAIK, không có cách nào để sandbox chúng theo cùng một cách không có cách nào để sandbox một đối tượng từ một đối tượng khác trong cùng một quy trình (cố gắng tại Ruby sandboxing mặc dù).
Chris McCauley

1
và Do hiểu Rack khác với Rake.
Manish Shrivastava

1
Tôi thích nghĩ phần mềm trung gian là bất cứ thứ gì nằm ở giữa ứng dụng của tôi giữa những gì tôi đã mã hóa và những gì đi đến và từ máy chủ của tôi ... được lưu trữ trên rackspace. Lý do 'thuật ngữ trung gian rack' gây nhầm lẫn, như chúng ta đều biết, là bởi vì chính Khổng Tử đã viết tất cả các phần mềm trung gian giá gốc, hơn 2000 năm trước. Ở Pháp.
LpLrich 10/03/2015

74

Trước hết, Rack chính xác là hai điều:

  • Một quy ước giao diện máy chủ web
  • Một viên ngọc

Rack - Giao diện máy chủ web

Những điều cơ bản của rack là một quy ước đơn giản. Mỗi máy chủ web tuân thủ giá sẽ luôn gọi một phương thức gọi trên một đối tượng bạn đưa cho anh ta và phục vụ kết quả của phương thức đó. Rack chỉ định chính xác cách thức phương thức cuộc gọi này trông như thế nào và nó phải trả về cái gì. Đó là giá đỡ.

Hãy thử một cách đơn giản. Tôi sẽ sử dụng WEBrick làm máy chủ web tuân thủ rack, nhưng bất kỳ ai trong số họ cũng sẽ làm được. Hãy tạo một ứng dụng web đơn giản trả về chuỗi JSON. Để làm điều này, chúng tôi sẽ tạo một tệp có tên config.ru. Các config.ru sẽ tự động được gọi bởi rackup của rack gem, đơn giản là sẽ chạy các nội dung của config.ru trong một máy chủ web tuân thủ rack. Vì vậy, hãy thêm phần sau vào tệp config.ru:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end

map '/hello.json' do
  run JSONServer.new
end

Vì quy ước chỉ định máy chủ của chúng tôi có một phương thức gọi là cuộc gọi chấp nhận hàm băm môi trường và trả về một mảng có dạng [trạng thái, tiêu đề, nội dung] để máy chủ web phục vụ. Hãy thử nó bằng cách gọi rackup. Một máy chủ tuân thủ giá mặc định, có thể WEBrick hoặc Mongrel sẽ khởi động và ngay lập tức chờ yêu cầu phục vụ.

$ rackup
[2012-02-19 22:39:26] INFO  WEBrick 1.3.1
[2012-02-19 22:39:26] INFO  ruby 1.9.3 (2012-01-17) [x86_64-darwin11.2.0]
[2012-02-19 22:39:26] INFO  WEBrick::HTTPServer#start: pid=16121 port=9292

Hãy kiểm tra máy chủ JSON mới của chúng tôi bằng cách cuộn tròn hoặc truy cập url http://localhost:9292/hello.jsonvà voila:

$ curl http://localhost:9292/hello.json
{ message: "Hello!" }

Nó hoạt động. Tuyệt quá! Đó là nền tảng cho mọi khung web, có thể là Rails hoặc Sinatra. Tại một số điểm, họ thực hiện một phương thức gọi, làm việc thông qua tất cả các mã khung và cuối cùng trả về một phản hồi ở dạng [trạng thái, tiêu đề, nội dung] điển hình.

Ví dụ, trong Ruby on Rails, các yêu cầu rack chạm vào ActionDispatch::Routing.Mapperlớp trông như thế này:

module ActionDispatch
  module Routing
    class Mapper
      ...
      def initialize(app, constraints, request)
        @app, @constraints, @request = app, constraints, request
      end

      def matches?(env)
        req = @request.new(env)
        ...
        return true
      end

      def call(env)
        matches?(env) ? @app.call(env) : [ 404, {'X-Cascade' => 'pass'}, [] ]
      end
      ...
  end
end

Vì vậy, về cơ bản Rails kiểm tra, phụ thuộc vào hàm băm env nếu bất kỳ tuyến nào khớp. Nếu vậy, nó chuyển hàm băm env cho ứng dụng để tính toán phản hồi, nếu không, nó sẽ phản hồi ngay lập tức với 404. Vì vậy, bất kỳ máy chủ web nào tuân thủ quy ước giao diện rack, đều có thể phục vụ ứng dụng Rails hoàn toàn.

Middleware

Rack cũng hỗ trợ việc tạo các lớp trung gian. Về cơ bản họ chặn một yêu cầu, làm một cái gì đó với nó và chuyển nó đi. Điều này rất hữu ích cho các nhiệm vụ linh hoạt.

Giả sử chúng tôi muốn thêm ghi nhật ký vào máy chủ JSON của chúng tôi để đo thời gian yêu cầu. Chúng ta chỉ cần tạo một logger phần mềm trung gian thực hiện chính xác điều này:

class RackLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)

    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

Khi được tạo, nó sẽ tự lưu một bản sao của ứng dụng rack thực tế. Trong trường hợp của chúng tôi, đó là một ví dụ của Máy chủ JSONS của chúng tôi. Rack tự động gọi phương thức gọi trên phần mềm trung gian và mong đợi trở lại một [status, headers, body]mảng, giống như trả về JSONServer của chúng tôi.

Vì vậy, trong phần mềm trung gian này, điểm bắt đầu được thực hiện, sau đó cuộc gọi thực tế đến Máy chủ JSONS được thực hiện @app.call(env), sau đó trình ghi nhật ký xuất mục nhập nhật ký và cuối cùng trả về phản hồi là [@status, @headers, @body].

Để làm cho rackup.ru nhỏ của chúng tôi sử dụng phần mềm trung gian này, hãy thêm sử dụng RackLogger vào nó như thế này:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end

class RackLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)

    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

use RackLogger

map '/hello.json' do
  run JSONServer.new
end   

Khởi động lại máy chủ và voila, nó xuất ra một bản ghi trên mỗi yêu cầu. Rack cho phép bạn thêm nhiều phần mềm trung gian được gọi theo thứ tự chúng được thêm vào. Đó chỉ là một cách tuyệt vời để thêm chức năng mà không thay đổi lõi của ứng dụng rack.

Giá đỡ - Đá quý

Mặc dù giá đỡ - trước hết - là một quy ước, nó cũng là một viên đá quý cung cấp chức năng tuyệt vời. Một trong số chúng tôi đã sử dụng cho máy chủ JSON của mình, lệnh rackup. Nhưng còn nhiều hơn thế! Giá đỡ cung cấp các ứng dụng nhỏ cho nhiều trường hợp sử dụng, như phục vụ các tệp tĩnh hoặc thậm chí toàn bộ thư mục. Hãy xem cách chúng tôi phục vụ một tệp đơn giản, ví dụ: tệp HTML rất cơ bản có tại htmls / index.html:

<!DOCTYPE HTML>
  <html>
  <head>
    <title>The Index</title>
  </head>

  <body>
    <p>Index Page</p>
  </body>
</html>

Chúng tôi có thể muốn phân phát tệp này từ thư mục gốc của trang web, vì vậy hãy thêm phần sau vào config.ru:

map '/' do
  run Rack::File.new "htmls/index.html"
end

Nếu chúng tôi truy cập, http://localhost:9292chúng tôi thấy tệp html của chúng tôi được hiển thị hoàn hảo. Điều đó thật dễ dàng phải không?

Chúng ta hãy thêm toàn bộ thư mục các tệp javascript bằng cách tạo một số tệp javascript trong / javascripts và thêm phần sau vào config.ru:

map '/javascripts' do
  run Rack::Directory.new "javascripts"
end

Khởi động lại máy chủ và truy cập http://localhost:9292/javascriptvà bạn sẽ thấy một danh sách tất cả các tệp javascript mà bạn có thể bao gồm ngay bây giờ từ bất cứ đâu.


3
Nhưng không phải trung gian Rack?
Rup

1
Nếu bạn không biết giá đỡ là gì, bạn sẽ biết chính xác nó là gì cách sử dụng nó sau khi bạn đọc bài đăng trên blog này. Rất đẹp. Trớ trêu thay, mặc dù, liên kết đến tài liệu giá chính thức ở cuối bài không còn nữa!
Colin

Quyền của bạn, cảm ơn. Tôi bao gồm các nội dung vào bài viết và loại bỏ liên kết chết.
Thomas Fankhauser

Tôi sẽ nói rằng đó không phải là một quy ước. đó là một giao diện, một hợp đồng được xác định rõ ràng cho mô hình đáp ứng yêu cầu
Ron Klein

20

Tôi đã có một vấn đề hiểu bản thân Rack trong một khoảng thời gian tốt. Tôi chỉ hoàn toàn hiểu nó sau khi tự mình làm máy chủ web Ruby thu nhỏ này . Tôi đã chia sẻ những kiến ​​thức của mình về Rack (dưới dạng một câu chuyện) tại đây trên blog của mình: http : //gaurav Touche.com/what-is-rack-in-ruby-rails

Phản hồi được chào đón nhiều hơn.


13
Các câu trả lời chỉ liên kết không được khuyến khích trên Stack Overflow , bởi vì nếu tài nguyên mà liên kết sẽ không có sẵn trong tương lai, câu trả lời sẽ trở nên vô dụng. Vui lòng ít nhất tóm tắt các điểm có liên quan của bài đăng trên blog của bạn và thêm chúng vào câu trả lời này.

Cảm ơn bạn đã gửi bài. Tôi là một lập trình viên Rails rất mới bắt đầu và tôi hiểu khái niệm rack với bài đăng rõ ràng của bạn.
Eduardo Ramos

Bài đăng trên blog tuyệt vời. Các câu trả lời khác có vẻ phức tạp hơn một chút IMO.
Ngao

Thật là một lời giải thích tuyệt vời. Cảm ơn, Gaurav.
rovitulli

7

config.ru ví dụ runnable tối thiểu

app = Proc.new do |env|
  [
    200,
    {
      'Content-Type' => 'text/plain'
    },
    ["main\n"]
  ]
end

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    @status, @headers, @body = @app.call(env)
    [@status, @headers, @body << "Middleware\n"]
  end
end

use(Middleware)

run(app)

Chạy rackupvà tham quan localhost:9292. Đầu ra là:

main
Middleware

Vì vậy, rõ ràng là Middlewarekết thúc tốt đẹp và gọi ứng dụng chính. Do đó, nó có thể xử lý trước yêu cầu và xử lý sau phản hồi theo bất kỳ cách nào.

Như đã giải thích tại: http://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack , Rails sử dụng phần mềm trung gian Rack cho rất nhiều chức năng của nó và bạn có thể thêm bạn sở hữu config.middleware.usephương thức gia đình.

Ưu điểm của việc triển khai chức năng trong một phần mềm trung gian là bạn có thể sử dụng lại nó trên bất kỳ khung Rack nào, do đó, tất cả các Ruby chính, và không chỉ Rails.


6

Rack middleware là một cách để lọc một yêu cầu và phản hồi đến ứng dụng của bạn. Một thành phần phần mềm trung gian nằm giữa máy khách và máy chủ, xử lý các yêu cầu gửi đến và phản hồi ra ngoài, nhưng nó không chỉ là giao diện có thể được sử dụng để nói chuyện với máy chủ web. Nó được sử dụng để nhóm và sắp xếp các mô-đun, thường là các lớp Ruby và chỉ định sự phụ thuộc giữa chúng. Mô-đun phần mềm trung gian giá chỉ phải: - có hàm tạo lấy ứng dụng tiếp theo trong ngăn xếp làm tham số - đáp ứng với phương thức gọi cuộc gọi, lấy hàm băm môi trường làm tham số. Trả về giá trị từ cuộc gọi này là một mảng gồm: mã trạng thái, hàm băm môi trường và phần thân phản hồi.


4

Tôi đã sử dụng phần mềm trung gian Rack để giải quyết một số vấn đề:

  1. Bắt lỗi phân tích cú pháp JSON với phần mềm trung gian Rack tùy chỉnh và trả về các thông báo lỗi được định dạng độc đáo khi máy khách gửi JSON bị lỗi
  2. Nén nội dung qua Rack :: Deflater

Nó có khả năng sửa chữa khá thanh lịch trong cả hai trường hợp.


2
Câu trả lời này, mặc dù hơi hữu ích, nhưng thực tế không giải quyết được câu hỏi Rack Middleware là gì .

Ngoài ra, đây là câu trả lời khá liên kết ...: P
Smar

4

Giá đỡ là gì?

Rack cung cấp một giao diện tối thiểu giữa các máy chủ web hỗ trợ các khung Ruby và Ruby.

Sử dụng Rack bạn có thể viết một ứng dụng Rack.

Rack sẽ chuyển băm Môi trường (một Hash, chứa trong yêu cầu HTTP từ máy khách, bao gồm các tiêu đề giống CGI) cho Ứng dụng Rack của bạn, có thể sử dụng những thứ có trong hàm băm này để làm bất cứ điều gì nó muốn.

Ứng dụng Rack là gì?

Để sử dụng Rack, bạn phải cung cấp 'ứng dụng' - một đối tượng phản hồi #callphương thức với Môi trường Hash dưới dạng tham số (thường được xác định là env). #callphải trả về một mảng có đúng ba giá trị:

  • các Status Mã (ví dụ như '200'),
  • một tiêu đề ,
  • các phản ứng cơ thể (mà phải đáp ứng với các phương pháp Ruby, each).

Bạn có thể viết Ứng dụng Rack trả về một mảng như vậy - điều này sẽ được gửi lại cho khách hàng của bạn, bởi Rack, bên trong Phản hồi (đây thực sự sẽ là một phiên bản của Class Rack::Response[nhấp để đi đến tài liệu]).

Một ứng dụng Rack rất đơn giản:

  • gem install rack
  • Tạo một config.rutập tin - Rack biết để tìm kiếm điều này.

Chúng tôi sẽ tạo một Ứng dụng Rack nhỏ trả về Phản hồi (ví dụ Rack::Response), Người phản hồi là một mảng có chứa Chuỗi : "Hello, World!".

Chúng tôi sẽ kích hoạt một máy chủ cục bộ bằng cách sử dụng lệnh rackup.

Khi truy cập cổng có liên quan trong trình duyệt của chúng tôi, chúng tôi sẽ thấy "Xin chào, Thế giới!" được hiển thị trong khung nhìn.

#./message_app.rb
class MessageApp
  def call(env)
    [200, {}, ['Hello, World!']]
  end
end

#./config.ru
require_relative './message_app'

run MessageApp.new

Khởi động một máy chủ cục bộ với rackupvà truy cập localhost: 9292 và bạn sẽ thấy 'Xin chào, Thế giới!' kết xuất.

Đây không phải là một lời giải thích toàn diện, nhưng về cơ bản, điều xảy ra ở đây là Máy khách (trình duyệt) gửi Yêu cầu HTTP đến Rack, thông qua máy chủ cục bộ của bạn và Rack khởi tạo MessageAppvà chạy call, chuyển trong Môi trường Hash dưới dạng tham số vào phương thức ( các envtham số).

Rack lấy giá trị trả về (mảng) và sử dụng nó để tạo một thể hiện Rack::Responsevà gửi nó trở lại Máy khách. Trình duyệt sử dụng phép thuật để in 'Xin chào, Thế giới!' đến màn hình.

Ngẫu nhiên, nếu bạn muốn xem băm môi trường trông như thế nào, chỉ cần đặt puts envbên dướidef call(env) .

Tối thiểu như nó là, những gì bạn đã viết ở đây là một ứng dụng Rack!

Làm cho Ứng dụng Rack tương tác với hàm băm Môi trường đến

Trong ứng dụng Rack nhỏ của chúng tôi, chúng tôi có thể tương tác với envhàm băm (xem tại đây để biết thêm về băm Môi trường).

Chúng tôi sẽ triển khai khả năng người dùng nhập chuỗi truy vấn của riêng họ vào URL, do đó, chuỗi đó sẽ có mặt trong yêu cầu HTTP, được gói gọn dưới dạng một giá trị trong một trong các cặp khóa / giá trị của hàm băm Môi trường.

Ứng dụng Rack của chúng tôi sẽ truy cập chuỗi truy vấn đó từ hàm băm Môi trường và gửi lại cho khách hàng (trình duyệt của chúng tôi, trong trường hợp này) thông qua Phần thân trong Phản hồi.

Từ các tài liệu Rack trên Hash môi trường: "QUERY_STRING: Phần của URL yêu cầu theo sau ?, Nếu có. Có thể trống, nhưng luôn luôn được yêu cầu!"

#./message_app.rb
class MessageApp
  def call(env)
    message = env['QUERY_STRING']
    [200, {}, [message]]
  end
end

Bây giờ, rackupvà truy cập localhost:9292?hello( ?hellolà chuỗi truy vấn) và bạn sẽ thấy 'xin chào' được hiển thị trong chế độ xem.

Giá đỡ trung gian

Chúng tôi sẽ:

  • chèn một phần của Middle Middleware vào cơ sở mã của chúng tôi - một lớp : MessageSetter,
  • Băm môi trường sẽ tấn công lớp này trước tiên và sẽ được truyền vào dưới dạng tham số : env,
  • MessageSettersẽ chèn một 'MESSAGE'khóa vào hàm băm env, giá trị của nó là 'Hello, World!'nếu env['QUERY_STRING']trống; env['QUERY_STRING']nếu không,
  • cuối cùng, nó sẽ trở lại @app.call(env)- @applà ứng dụng tiếp theo trong 'Stack' : MessageApp.

Đầu tiên, phiên bản 'tay dài':

#./middleware/message_setter.rb
class MessageSetter
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['QUERY_STRING'].empty?
      env['MESSAGE'] = 'Hello, World!'
    else
      env['MESSAGE'] = env['QUERY_STRING']
    end
    @app.call(env)
  end
end

#./message_app.rb (same as before)
class MessageApp
  def call(env)
    message = env['QUERY_STRING']
    [200, {}, [message]]
  end
end

#config.ru
require_relative './message_app'
require_relative './middleware/message_setter'

app = Rack::Builder.new do
  use MessageSetter
  run MessageApp.new
end

run app

Từ các tài liệu Rack :: Builder chúng ta thấy rằngRack::Builder thực hiện một DSL nhỏ để lặp lại các ứng dụng Rack. Về cơ bản, điều này có nghĩa là bạn có thể xây dựng một 'Ngăn xếp' bao gồm một hoặc nhiều Middleware và ứng dụng 'cấp dưới' để gửi tới. Tất cả các yêu cầu chuyển đến ứng dụng cấp dưới của bạn sẽ được xử lý trước bởi (các) Middleware của bạn.

#usechỉ định phần mềm trung gian để sử dụng trong ngăn xếp. Nó lấy phần mềm trung gian làm đối số.

Rack Middleware phải:

  • có một hàm tạo lấy ứng dụng tiếp theo trong ngăn xếp làm tham số.
  • đáp ứng với callphương thức lấy hàm băm Môi trường làm tham số.

Trong trường hợp của chúng tôi, 'Middleware' là MessageSetter, 'constructor' là initializephương thức của MessageSetter , 'ứng dụng tiếp theo' trong ngăn xếp làMessageApp .

Vì vậy, ở đây, vì những gì Rack::Builderkhông dưới mui xe, các appđối số của MessageSetter's initializephương pháp là MessageApp.

(hãy tập trung vào những điều trên trước khi tiếp tục)

Do đó, mỗi phần của Middleware về cơ bản 'truyền' băm Môi trường hiện tại cho ứng dụng tiếp theo trong chuỗi - vì vậy bạn có cơ hội để biến đổi băm môi trường đó trong Middleware trước khi chuyển nó sang ứng dụng tiếp theo trong ngăn xếp.

#runnhận một đối số là một đối tượng phản hồi #callvà trả về một Phản hồi giá (một thể hiện của Rack::Response).

Kết luận

Sử dụng Rack::Builderbạn có thể xây dựng chuỗi Middleware và mọi yêu cầu cho ứng dụng của bạn sẽ được xử lý lần lượt bởi mỗi Middleware trước khi cuối cùng được xử lý bởi phần cuối cùng trong ngăn xếp (trong trường hợp của chúng tôi,MessageApp ). Điều này cực kỳ hữu ích vì nó tách ra các giai đoạn xử lý yêu cầu khác nhau. Về mặt 'phân tách mối quan tâm', nó không thể sạch sẽ hơn nhiều!

Bạn có thể xây dựng một 'đường ống yêu cầu' bao gồm một số Middleware xử lý những thứ như:

  • Xác thực
  • Ủy quyền
  • Bộ nhớ đệm
  • Trang trí
  • Giám sát hiệu suất và sử dụng
  • Thực thi (thực sự xử lý yêu cầu và cung cấp phản hồi)

(trên các gạch đầu dòng từ một câu trả lời khác về chủ đề này)

Bạn sẽ thường thấy điều này trong các ứng dụng Sinatra chuyên nghiệp. Sinatra sử dụng Rack! Xem ở đây để định nghĩa về Sinatra IS !

Như một lưu ý cuối cùng, chúng ta config.rucó thể được viết theo kiểu tay ngắn, tạo ra chính xác cùng chức năng (và đây là những gì bạn thường thấy):

require_relative './message_app'
require_relative './middleware/message_setter'

use MessageSetter
run MessageApp.new

Và để thể hiện rõ hơn những gì MessageAppđang làm, đây là phiên bản 'tay dài' của nó cho thấy rõ ràng rằng nó #callđang tạo ra một thể hiện mới Rack::Response, với ba đối số được yêu cầu.

class MessageApp
  def call(env)
    Rack::Response.new([env['MESSAGE']], 200, {})
  end
end

Liên kết hữu ích


1

Rack - Giao diện b / w Web & App Server

Rack là gói Ruby cung cấp giao diện cho máy chủ web để giao tiếp với ứng dụng. Thật dễ dàng để thêm các thành phần phần mềm trung gian giữa máy chủ web và ứng dụng để sửa đổi cách ứng xử / yêu cầu của bạn. Thành phần phần mềm trung gian nằm giữa máy khách và máy chủ, xử lý các yêu cầu gửi đến và phản hồi ra ngoài.

Nói một cách dễ hiểu, về cơ bản, đây chỉ là một bộ hướng dẫn về cách một máy chủ và ứng dụng Rails (hoặc bất kỳ ứng dụng web Ruby nào khác) nên nói chuyện với nhau .

Để sử dụng Rack, hãy cung cấp "ứng dụng": một đối tượng phản hồi lại phương thức gọi, lấy hàm băm môi trường làm tham số và trả về một mảng có ba phần tử:

  • Mã phản hồi HTTP
  • Một tiêu đề
  • Các cơ quan đáp ứng , phải đáp ứng với từng yêu cầu .

Để giải thích thêm, bạn có thể theo các liên kết dưới đây.

1. https://rack.github.io/
2. https://redpanthers.co/rack-middleware/
3. https://blog.engineyard.com/2015/understanding-rack-apps-and-middleware
4. https://guides.rubyonrails.org/rails_on_rack.html#resources

Trong rails, chúng tôi có config.ru dưới dạng tệp rack, bạn có thể chạy bất kỳ tệp rack nào bằng rackuplệnh. Và cổng mặc định cho việc này là 9292. Để kiểm tra điều này, bạn chỉ cần chạy rackuptrong thư mục rails của bạn và xem kết quả. Bạn cũng có thể gán cổng mà bạn muốn chạy nó. Lệnh chạy tệp rack trên bất kỳ cổng cụ thể nào là

rackup -p PORT_NUMBER

1

hình ảnh hiển thị giá ở giữa kỳ lân và đường ray

Rack là một viên ngọc cung cấp giao diện đơn giản cho yêu cầu / phản hồi HTTP trừu tượng. Rack nằm giữa các khung web (Rails, Sinatra, v.v.) và các máy chủ web (kỳ lân, puma) như một bộ chuyển đổi. Từ hình ảnh trên, điều này giữ cho máy chủ kỳ lân hoàn toàn độc lập với việc biết về đường ray và đường ray không biết về kỳ lân. Đây là một ví dụ tốt về khớp nối lỏng lẻo , tách các mối quan tâm .

Hình trên là từ cuộc hội thảo rails này trên rack https://youtu.be/3PnUV9QzB0g Tôi khuyên bạn nên xem nó để hiểu sâu hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.