Ruby-on-rails 什么是机架中间件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2256569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is Rack middleware?
提问by chrisgoyal
What is Rack middleware in Ruby? I couldn't find any good explanation for what they mean by "middleware".
Ruby 中的 Rack 中间件是什么?对于“中间件”的含义,我找不到任何好的解释。
回答by Chris McCauley
Rack as Design
机架设计
Rack middleware is more than "a way to filter a request and response" - it's an implementation of the pipeline design patternfor web servers using Rack.
Rack 中间件不仅仅是“一种过滤请求和响应的方法”——它是使用Rack 的Web 服务器的管道设计模式的实现。
It very cleanly separates out the different stages of processing a request - separation of concerns being a key goal of all well designed software products.
它非常清晰地分离出处理请求的不同阶段——关注点分离是所有设计良好的软件产品的关键目标。
For example with Rack I can have separate stages of the pipeline doing:
例如,使用 Rack,我可以将管道的不同阶段分为:
Authentication: when the request arrives, are the users logon details correct? How do I validate this OAuth, HTTP Basic Authentication, name/password?
Authorisation: "is the user authorised to perform this particular task?", i.e. role-based security.
Caching: have I processed this request already, can I return a cached result?
Decoration: how can I enhance the request to make downstream processing better?
Performance & Usage Monitoring: what stats can I get from the request and response?
Execution: actually handle the request and provide a response.
身份验证:请求到达时,用户登录详细信息是否正确?如何验证此 OAuth、HTTP 基本身份验证、名称/密码?
授权:“用户是否有权执行此特定任务?”,即基于角色的安全性。
缓存:我已经处理了这个请求,我可以返回一个缓存的结果吗?
装修:如何增强请求,使下游处理更好?
性能和使用情况监控:我可以从请求和响应中获得哪些统计信息?
执行:实际处理请求并提供响应。
Being able to separate the different stages (and optionally include them) is a great help in developing well structured applications.
能够分离不同的阶段(并可选地包括它们)对开发结构良好的应用程序有很大帮助。
Community
社区
There's also a great eco-system developing around Rack Middleware - you should be able to find pre-built rack components to do all of the steps above and more. See the Rack GitHub wiki for a list of middleware.
还有一个围绕机架中间件开发的很棒的生态系统 - 您应该能够找到预构建的机架组件来执行上述所有步骤以及更多步骤。请参阅Rack GitHub wiki 以获取中间件列表。
What's Middleware?
什么是中间件?
Middleware is a dreadful term which refers to any software component/library which assists with but is not directly involved in the execution of some task. Very common examples are logging, authentication and the other common, horizontal processing components. These tend to be the things that everyone needs across multiple applications but not too many people are interested (or should be) in building themselves.
中间件是一个可怕的术语,它指的是任何协助但不直接参与某些任务执行的软件组件/库。非常常见的示例是日志记录、身份验证和其他常见的水平处理组件。这些往往是每个人在多个应用程序中都需要的东西,但没有太多人对构建自己感兴趣(或应该)。
More Information
更多信息
The comment about it being a way to filter requests probably comes from the RailsCast episode 151: Rack Middlewarescreen cast.
Rack middleware evolved out of Rack and there is a great intro at Introduction to Rack middleware.
There's an intro to middleware on Wikipedia here.
关于它是一种过滤请求的方法的评论可能来自RailsCast 第 151 集:机架中间件屏幕投射。
Rack中间件演变机架的查明是在一个伟大的介绍介绍Rack中间件。
有一个介绍中间件在维基百科上这里。
回答by Thomas Fankhauser
First of all, Rack is exactly two things:
首先,Rack 正是两件事:
- A webserver interface convention
- A gem
- 网络服务器接口约定
- 一颗宝石
Rack - The Webserver Interface
Rack - Web 服务器界面
The very basics of rack is a simple convention. Every rack compliant webserver will always call a call method on an object you give him and serve the result of that method. Rack specifies exactly how this call method has to look like, and what it has to return. That's rack.
机架的基础是一个简单的约定。每个机架兼容的网络服务器总是会在你给他的对象上调用一个 call 方法,并提供该方法的结果。Rack 准确地指定了这个调用方法的外观,以及它必须返回的内容。那是架子。
Let's give it a simple try. I'll use WEBrick as rack compliant webserver, but any of them will do. Let's create a simple web application that returns a JSON string. For this we'll create a file called config.ru. The config.ru will automatically be called by the rack gem's command rackup which will simply run the contents of the config.ru in a rack-compliant webserver. So let's add the following to the config.ru file:
让我们来做一个简单的尝试。我将使用 WEBrick 作为机架兼容的网络服务器,但它们中的任何一个都可以。让我们创建一个返回 JSON 字符串的简单 Web 应用程序。为此,我们将创建一个名为 config.ru 的文件。config.ru 将被 rack gem 的命令 rackup 自动调用,它会在一个兼容机架的网络服务器中简单地运行 config.ru 的内容。因此,让我们将以下内容添加到 config.ru 文件中:
class JSONServer
def call(env)
[200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
end
end
map '/hello.json' do
run JSONServer.new
end
As the convention specifies our server has a method called call that accepts an environment hash and returns an array with the form [status, headers, body] for the webserver to serve. Let's try it out by simply calling rackup. A default rack compliant server, maybe WEBrick or Mongrel will start and immediately wait for requests to serve.
按照惯例,我们的服务器有一个名为 call 的方法,它接受环境哈希并返回一个数组,格式为 [状态、标题、正文],供网络服务器提供服务。让我们通过简单地调用 rackup 来尝试一下。默认的机架兼容服务器,也许 WEBrick 或 Mongrel 将启动并立即等待请求服务。
$ 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
Let's test our new JSON server by either curling or visiting the url http://localhost:9292/hello.jsonand voila:
让我们通过 curl 或访问 url 来测试我们的新 JSON 服务器http://localhost:9292/hello.json,瞧:
$ curl http://localhost:9292/hello.json
{ message: "Hello!" }
It works. Great! That's the basis for every web framework, be it Rails or Sinatra. At some point they implement a call method, work through all the framework code, and finally return a response in the typical [status, headers, body] form.
有用。伟大的!这是每个 Web 框架的基础,无论是 Rails 还是 Sinatra。在某些时候,他们实现一个调用方法,处理所有框架代码,最后以典型的 [状态、标题、正文] 形式返回响应。
In Ruby on Rails for example the rack requests hits the ActionDispatch::Routing.Mapperclass which looks like this:
例如,在 Ruby on Rails 中,机架请求会命中如下所示的ActionDispatch::Routing.Mapper类:
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
So basically Rails checks, dependent on the env hash if any route matches. If so it passes the env hash on to the application to compute the response, otherwise it immediately responds with a 404. So any webserver that is is compliant with the rack interface convention, is able to serve a fully blown Rails application.
所以基本上 Rails 检查,如果有任何路由匹配,依赖于 env 哈希。如果是这样,它会将 env 散列传递给应用程序以计算响应,否则它会立即以 404 响应。因此,任何符合机架接口约定的 Web 服务器都能够为完全成熟的 Rails 应用程序提供服务。
Middleware
中间件
Rack also supports the creation of middleware layers. They basically intercept a request, do something with it and pass it on. This is very useful for versatile tasks.
Rack 还支持创建中间件层。他们基本上拦截一个请求,用它做一些事情并传递它。这对于多功能任务非常有用。
Let's say we want to add logging to our JSON server that also measures how long a request takes. We can simply create a middleware logger that does exactly this:
假设我们想向我们的 JSON 服务器添加日志记录,它还可以测量请求花费的时间。我们可以简单地创建一个中间件记录器来做到这一点:
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
When it gets created, it saves itself a copy of the actual rack application. In our case that's an instance of our JSONServer. Rack automatically calls the call method on the middleware and expects back a [status, headers, body]array, just like our JSONServer returns.
当它被创建时,它会为自己保存一份实际机架应用程序的副本。在我们的例子中,这是我们 JSONServer 的一个实例。Rack 自动调用中间件上的 call 方法并期望返回一个[status, headers, body]数组,就像我们的 JSONServer 返回一样。
So in this middleware, the start point is taken, then the actual call to the JSONServer is made with @app.call(env), then the logger outputs the logging entry and finally returns the response as [@status, @headers, @body].
因此,在这个中间件中,取起点,然后使用 对 JSONServer 进行实际调用@app.call(env),然后记录器输出日志条目,最后将响应返回为[@status, @headers, @body]。
To make our little rackup.ru use this middleware, add a use RackLogger to it like this:
为了让我们的小 rackup.ru 使用这个中间件,像这样添加一个 use RackLogger 到它:
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
Restart the server and voila, it outputs a log on every request. Rack allows you to add multiple middlewares that are called in the order they are added. It's just a great way to add functionality without changing the core of the rack application.
重新启动服务器,瞧,它会在每个请求上输出一个日志。Rack 允许您添加多个按添加顺序调用的中间件。这只是在不改变机架应用程序核心的情况下添加功能的好方法。
Rack - The Gem
机架 - 宝石
Although rack - first of all - is a convention it also is a gem that provides great functionality. One of them we already used for our JSON server, the rackup command. But there's more! The rack gem provides little applications for lots of use cases, like serving static files or even whole directories. Let's see how we serve a simple file, for example a very basic HTML file located at htmls/index.html:
尽管机架 - 首先 - 是一种惯例,但它也是提供强大功能的宝石。其中之一我们已经用于我们的 JSON 服务器,rackup 命令。但还有更多!rack gem 为许多用例提供很少的应用程序,比如提供静态文件甚至整个目录。让我们看看我们如何提供一个简单的文件,例如位于 htmls/index.html 的一个非常基本的 HTML 文件:
<!DOCTYPE HTML>
<html>
<head>
<title>The Index</title>
</head>
<body>
<p>Index Page</p>
</body>
</html>
We maybe want to serve this file from the website root, so let's add the following to our config.ru:
我们可能希望从网站根目录提供此文件,因此让我们将以下内容添加到我们的 config.ru 中:
map '/' do
run Rack::File.new "htmls/index.html"
end
If we visit http://localhost:9292we see our html file perfectly rendered. That's was easy, right?
如果我们访问,http://localhost:9292我们会看到我们的 html 文件完美呈现。那很容易,对吧?
Let's add a whole directory of javascript files by creating some javascript files under /javascripts and adding the following to the config.ru:
让我们通过在 /javascripts 下创建一些 javascript 文件并将以下内容添加到 config.ru 来添加整个 javascript 文件目录:
map '/javascripts' do
run Rack::Directory.new "javascripts"
end
Restart the server and visit http://localhost:9292/javascriptand you'll see a list of all javascript files you can include now straight from anywhere.
重新启动服务器并访问http://localhost:9292/javascript,您将看到您现在可以直接从任何地方包含的所有 javascript 文件的列表。
回答by Gaurav Chande
I had a problem understanding Rack myself for a good amount of time. I only fully understood it after working on making this miniature Ruby web servermyself. I've shared my learnings about Rack (in the form of a story) here on my blog: http://gauravchande.com/what-is-rack-in-ruby-rails
我在很长一段时间内都无法理解 Rack。我是在自己制作这个微型 Ruby Web 服务器之后才完全理解它的。我在我的博客上分享了我对 Rack 的了解(以故事的形式):http: //gauravchande.com/what-is-rack-in-ruby-rails
Feedback is more than welcome.
非常欢迎反馈。
回答by L.Cole
Rack middleware is a way to filter a request and response coming into your application. A middleware component sits between the client and the server, processing inbound requests and outbound responses, but it's more than interface that can be used to talk to web server. It's used to group and order modules, which are usually Ruby classes, and specify dependency between them. Rack middleware module must only: – have constructor that takes next application in stack as parameter – respond to “call” method, that takes environment hash as a parameter. Returning value from this call is an array of: status code, environment hash and response body.
机架中间件是一种过滤进入应用程序的请求和响应的方法。中间件组件位于客户端和服务器之间,处理入站请求和出站响应,但它不仅仅是可用于与 Web 服务器通信的接口。它用于对模块(通常是 Ruby 类)进行分组和排序,并指定它们之间的依赖关系。机架中间件模块必须仅: – 具有将堆栈中的下一个应用程序作为参数的构造函数 – 响应“调用”方法,将环境哈希作为参数。此调用的返回值是一个数组:状态代码、环境哈希和响应正文。
回答by Yorkshireman
What is Rack?
什么是机架?
Rack provides a minimal interface between between webservers supporting Ruby and Ruby frameworks.
Rack 在支持 Ruby 和 Ruby 框架的 web 服务器之间提供了一个最小的接口。
Using Rack you can write a Rack Application.
使用 Rack,您可以编写一个 Rack 应用程序。
Rack will pass the Environment hash (a Hash, contained inside a HTTP request from a client, consisting of CGI-like headers) to your Rack Application which can use things contained in this hash to do whatever it wants.
Rack 会将 Environment 散列(一个散列,包含在来自客户端的 HTTP 请求中,由类似 CGI 的标头组成)传递给您的 Rack 应用程序,该应用程序可以使用此散列中包含的内容来做任何它想做的事情。
What is a Rack Application?
什么是机架应用程序?
To use Rack, you must provide an 'app' - an object that responds to the #callmethod with the Environment Hash as a parameter (typically defined as env). #callmust return an Array of exactly three values:
要使用 Rack,您必须提供一个“应用程序”——一个以#callEnvironment Hash 作为参数响应方法的对象(通常定义为env)。#call必须返回一个正好包含三个值的数组:
- the Status Code(eg '200'),
- a Hash of Headers,
- the Response Body(which must respond to the Ruby method,
each).
- 的状态码(例如“200”),
- 头的哈希,
- 的响应体(必须向红宝石方法反应,
each)。
You can write a Rack Application that returns such an array - this will be sent back to your client, by Rack, inside a Response(this will actually be an instanceof the Class Rack::Response[click to go to docs]).
您可以编写一个返回这样一个数组的 Rack 应用程序 - 这将通过 Rack 在响应中发送回您的客户端(这实际上是类的一个实例Rack::Response[单击转到文档])。
A Very Simple Rack Application:
一个非常简单的机架应用程序:
gem install rack- Create a
config.rufile - Rack knows to look for this.
gem install rack- 创建一个
config.ru文件——Rack 知道要查找这个文件。
We will create a tiny Rack Application that returns a Response (an instance of Rack::Response) who's Response Body is an array that contains a String: "Hello, World!".
我们将创建一个微型 Rack 应用程序,它返回一个 Response( 的实例Rack::Response),其 Response Body 是一个包含 String: 的数组"Hello, World!"。
We will fire up a local server using the command rackup.
我们将使用命令启动本地服务器rackup。
When visiting the relevant port in our browser we will see "Hello, World!" rendered in the viewport.
在浏览器中访问相关端口时,我们将看到“Hello, World!” 在视口中呈现。
#./message_app.rb
class MessageApp
def call(env)
[200, {}, ['Hello, World!']]
end
end
#./config.ru
require_relative './message_app'
run MessageApp.new
Fire up a local server with rackupand visit localhost:9292and you should see 'Hello, World!' rendered.
启动本地服务器rackup并访问localhost:9292,您应该会看到“Hello, World!” 呈现。
This is not a comprehensive explanation, but essentially what happens here is that the Client (the browser) sends a HTTP Request to Rack, via your local server, and Rack instantiates MessageAppand runs call, passing in the Environment Hash as a parameter into the method (the envargument).
这不是一个全面的解释,但本质上这里发生的是客户端(浏览器)通过本地服务器向 Rack 发送 HTTP 请求,然后 Rack 实例化MessageApp并运行call,将 Environment Hash 作为参数传递到方法中(该env参数)。
Rack takes the return value (the array) and uses it to create an instance of Rack::Responseand sends that back to the Client. The browser uses magicto print 'Hello, World!' to the screen.
Rack 获取返回值(数组)并使用它来创建一个实例Rack::Response并将其发送回客户端。浏览器使用魔法打印“Hello, World!” 到屏幕。
Incidentally, if you want to see what the environment hash looks like, just put puts envunderneath def call(env).
顺便说一句,如果你想看到什么环境散的样子,只是把puts env底下def call(env)。
Minimal as it is, what you have written here is a Rack application!
尽管它是最小的,但您在此处编写的是 Rack 应用程序!
Making a Rack Application interact with the Incoming Environment hash
使机架应用程序与传入环境哈希交互
In our little Rack app, we can interact with the envhash (see herefor more about the Environment hash).
在我们的小 Rack 应用程序中,我们可以与env散列进行交互(有关环境散列的更多信息,请参见此处)。
We will implement the ability for the user to input their own query string into the URL, hence, that string will be present in the HTTP request, encapsulated as a value in one of the key/value pairs of the Environment hash.
我们将实现用户将他们自己的查询字符串输入 URL 的能力,因此,该字符串将出现在 HTTP 请求中,封装为环境哈希的键/值对之一中的值。
Our Rack app will access that query string from the Environment hash and send that back to the client (our browser, in this case) via the Body in the Response.
我们的 Rack 应用程序将从 Environment 哈希中访问该查询字符串,并通过响应中的正文将其发送回客户端(在本例中为我们的浏览器)。
From the Rack docs on the Environment Hash: "QUERY_STRING: The portion of the request URL that follows the ?, if any. May be empty, but is always required!"
来自 Environment Hash 上的 Rack 文档: “QUERY_STRING:请求 URL 后面的部分?,如果有。可能为空,但始终是必需的!”
#./message_app.rb
class MessageApp
def call(env)
message = env['QUERY_STRING']
[200, {}, [message]]
end
end
Now, rackupand visit localhost:9292?hello(?hellobeing the query string) and you should see 'hello' rendered in the viewport.
现在,rackup访问localhost:9292?hello(?hello作为查询字符串),您应该会在视口中看到“hello”。
Rack Middleware
机架中间件
We will:
我们会:
- insert a piece of Rack Middleware into our codebase - a class:
MessageSetter, - the Environment hash will hit this class first and will be passed in as a parameter:
env, MessageSetterwill insert a'MESSAGE'key into the env hash, its value being'Hello, World!'ifenv['QUERY_STRING']is empty;env['QUERY_STRING']if not,- finally, it will return
@app.call(env)-@appbeing the next app in the 'Stack':MessageApp.
- 插入了一段Rack中间件到我们的代码库-一类:
MessageSetter, - Environment hash 将首先命中这个类,并将作为参数传入:
env, MessageSetter将'MESSAGE'在 env 哈希中插入一个键,其值为'Hello, World!'ifenv['QUERY_STRING']为空;env['QUERY_STRING']如果不,- 最后,它将返回
@app.call(env)-@app成为“堆栈”中的下一个应用程序:MessageApp。
First, the 'long-hand' version:
首先,“长手”版本:
#./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
From the Rack::Builder docswe see that Rack::Builderimplements a small DSL to iteratively construct Rack applications. This basically means that you can build a 'Stack' consisting of one or more Middlewares and a 'bottom level' application to dispatch to. All requests going through to your bottom-level application will be first processed by your Middleware(s).
从Rack::Builder 文档中,我们看到它Rack::Builder实现了一个小的 DSL 来迭代构建 Rack 应用程序。这基本上意味着您可以构建一个由一个或多个中间件和一个“底层”应用程序组成的“堆栈”以进行分派。通过您的底层应用程序的所有请求将首先由您的中间件处理。
#usespecifies middleware to use in a stack. It takes the middleware as an argument.
#use指定要在堆栈中使用的中间件。它以中间件为参数。
Rack Middleware must:
机架中间件必须:
- have a constructor that takes the next application in the stack as a parameter.
- respond to the
callmethod that takes the Environment hash as a parameter.
- 有一个构造函数,它将堆栈中的下一个应用程序作为参数。
- 响应
call将 Environment 哈希作为参数的方法。
In our case, the 'Middleware' is MessageSetter, the 'constructor' is MessageSetter's initializemethod, the 'next application' in the stack is MessageApp.
在我们的例子中,“中间件”是MessageSetter,“构造函数”是 MessageSetter 的initialize方法,堆栈中的“下一个应用程序”是MessageApp。
So here, because of what Rack::Builderdoes under the hood, the appargument of MessageSetter's initializemethod is MessageApp.
所以在这里,因为在幕后Rack::Builder做了什么,的方法的app参数是.MessageSetterinitializeMessageApp
(get your head around the above before moving on)
(在继续之前请先了解上述内容)
Therefore, each piece of Middleware essentially 'passes down' the existing Environment hash to the next application in the chain - so you have the opportunity to mutate that environment hash within the Middleware before passing it on to the next application in the stack.
因此,每个中间件本质上都将现有的环境哈希“向下传递”到链中的下一个应用程序 - 因此您有机会在中间件中改变该环境哈希,然后再将其传递给堆栈中的下一个应用程序。
#runtakes an argument that is an object that responds to #calland returns a Rack Response (an instance of Rack::Response).
#run接受一个参数,该参数是一个响应#call并返回机架响应( 的实例Rack::Response)的对象。
Conclusions
结论
Using Rack::Builderyou can construct chains of Middlewares and any request to your application will be processed by each Middleware in turn before finally being processed by the final piece in the stack (in our case, MessageApp). This is extremely useful because it separates-out different stages of processing requests. In terms of 'separation of concerns', it couldn't be much cleaner!
使用Rack::Builder您可以构建中间件链,并且对您的应用程序的任何请求将依次由每个中间件处理,然后最终由堆栈中的最后一块(在我们的例子中MessageApp)处理。这非常有用,因为它将处理请求的不同阶段分开。在“关注点分离”方面,它不可能更干净!
You can construct a 'request pipeline' consisting of several Middlewares that deal with things such as:
您可以构建一个“请求管道”,由几个处理诸如以下内容的中间件组成:
- Authentication
- Authorisation
- Caching
- Decoration
- Performance & Usage Monitoring
- Execution (actually handle the request and provide a response)
- 验证
- 授权
- 缓存
- 装饰
- 性能和使用监控
- 执行(实际处理请求并提供响应)
(above bullet points from another answer on this thread)
(以上来自该线程的另一个答案的要点)
You will often see this in professional Sinatra applications. Sinatra uses Rack! See herefor the definition of what Sinatra IS!
您会经常在专业的 Sinatra 应用程序中看到这一点。Sinatra 使用 Rack!见这里的什么西纳特拉的定义IS!
As a final note, our config.rucan be written in a short-hand style, producing exactly the same functionality (and this is what you'll typically see):
最后一点,我们config.ru可以用简写风格编写,产生完全相同的功能(这就是您通常会看到的):
require_relative './message_app'
require_relative './middleware/message_setter'
use MessageSetter
run MessageApp.new
And to show more explicitly what MessageAppis doing, here is its 'long-hand' version that explicitly shows that #callis creating a new instance of Rack::Response, with the required three arguments.
为了更明确地显示MessageApp正在做什么,这里是它的“长手”版本,它明确地显示#call正在创建 的新实例Rack::Response,并带有所需的三个参数。
class MessageApp
def call(env)
Rack::Response.new([env['MESSAGE']], 200, {})
end
end
Useful links
有用的链接
回答by djcp
I've used Rack middleware to solve a couple problems:
我使用 Rack 中间件解决了几个问题:
- Catching JSON parse errors with custom Rack middlewareand returning nicely formatted error messages when client submits busted JSON
- Content Compression via Rack::Deflater
- 使用自定义 Rack 中间件捕获 JSON 解析错误并在客户端提交破坏的 JSON 时返回格式良好的错误消息
- 通过 Rack::Deflater 进行内容压缩
It afforded pretty elegant fixes in both cases.
它在两种情况下都提供了非常优雅的修复。
回答by V K Singh
Rack - The Interface b/w Web & App Server
Rack - 界面 b/w Web & App Server
Rack is a Ruby package which provides an interface for a web server to communicate with the application. It is easy to add middleware components between the web server and the app to modify the way your request/response behaves. The middleware component sits between the client and the server, processing inbound requests and outbound responses.
Rack 是一个 Ruby 包,它为 Web 服务器与应用程序通信提供了一个接口。在 Web 服务器和应用程序之间添加中间件组件以修改请求/响应的行为方式很容易。中间件组件位于客户端和服务器之间,处理入站请求和出站响应。
In layman words, It is basically just a set of guidelines for how a server and a Rails app (or any other Ruby web app) should talk to each other.
通俗地说,它基本上只是关于服务器和 Rails 应用程序(或任何其他 Ruby Web 应用程序)应该如何相互通信的一组指南。
To use Rack, provide an "app": an object that responds to the call method, taking the environment hash as a parameter, and returning an Array with three elements:
要使用 Rack,请提供一个“应用程序”:一个响应调用方法的对象,将环境哈希作为参数,并返回一个包含三个元素的 Array:
- The HTTP response code
- A Hash of headers
- The response body, which must respond to each request.
- HTTP 响应代码
- 标题的哈希
- 所述反应体,它必须对每个响应请求。
For more explanation, you can follow the below links.
有关更多解释,您可以点击以下链接。
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
In rails, we have config.ru as a rack file, you can run any rack file with rackupcommand. And the default port for this is 9292. To test this, you can simply run rackupin your rails directory and see the result. You can also assign port on which you want to run it. Command to run rack file on any specific port is
在 rails 中,我们有 config.ru 作为机架文件,您可以使用rackup命令运行任何机架文件。这个的默认端口是9292. 要对此进行测试,您可以简单地rackup在 rails 目录中运行并查看结果。您还可以分配要运行它的端口。在任何特定端口上运行机架文件的命令是
rackup -p PORT_NUMBER
回答by Vbp
Rack is a gem which provides a simple interface to abstract HTTP request/response. Rack sits between web frameworks (Rails, Sinatra etc) and web servers (unicorn, puma) as an adaptor. From above image this keeps unicorn server completely independent from knowing about rails and rails doesn't know about unicorn. This is a good example of loose coupling, separation of concerns.
Rack 是一个 gem,它提供了一个简单的接口来抽象 HTTP 请求/响应。Rack 作为适配器位于 Web 框架(Rails、Sinatra 等)和 Web 服务器(unicorn、puma)之间。从上图可以看出,这使 unicorn 服务器完全独立于了解 rails 和 rails 不了解 unicorn。这是松耦合、关注点分离的一个很好的例子。
Above image is from this rails conference talk on rack https://youtu.be/3PnUV9QzB0gI recommend watching it for deeper understanding.
上图来自机架上的这个 rails 会议演讲https://youtu.be/3PnUV9QzB0g我建议观看它以加深理解。


