Rack
Rack既是一个规范,也是一个实现这个规范的Ruby库。
Rack充当了App Server(Unicorn,Puma等)和Web App(Rails,Sinatra)之间的桥梁。 符合Rack App规范的App Server和Web App可以轻松组合在一起。
Rack定义
Rack App的定义为:
A Rack application is a Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns a non-frozen Array of exactly three values: The status, the headers, and the body.
一个Rack App是一个响应call方法的Ruby对象(而不是类)。它只接受一个参数,即环境参数,并且返回一个包含HTTP状态码,头部,body的non-frozen数组
一个简单的Rack App:
|
|
环境参数的定义(The Environment)
The environment must be an unfrozen instance of Hash that includes CGI-like headers. The Rack application is free to modify the environment.
环境参数必须是一个Hash,它包含了一系列CGI风格头部,Rack App可以随意修改这个环境参数。 这里的CGI风格指的传统的CGI接口命名:
- 使用
大写字母 + 下划线
的命名方式,比如HTTP_HOST
、HTTP_USER_AGENT
。 - 以
HTTP_
开头的变量表示 HTTP 请求头。例如:- HTTP 请求头
Host: example.com
会映射为HTTP_HOST
。 - HTTP 请求头
User-Agent: curl/7.68.0
会映射为HTTP_USER_AGENT
。
- HTTP 请求头
例如:
|
|
规范里规定了一些除空值情况外必须包含的环境参数
App Server和Web App也可以在环境参数里保存自己的数据,需要注意的是,参数key必须包含一个.
,并且具有唯一的前缀。rack.
前缀是为rack库保留的,不能随意使用
The Input Stream
The input stream is an IO-like object which contains the raw HTTP POST data.
环境参数中的rack.input
存储了POST请求的原始数据,当可用时,它必须以ASCII 8bit
二进制编码的格式被打开,并且能响应gets
, each
, read
方法
rack.errors
与rack.input
类似,用于记录/响应错误。
响应
状态码
必须是大于等于100的整数HTTP状态码
头部
The headers must be a unfrozen Hash. The header keys must be Strings.
Body
The Body is typically an
Array
ofString
instances, anenumerable
that yieldsString
instances, aProc
instance, or aFile-like object
.
关于环境参数及响应的具体要求可以参考Rack SPEC。
Rack的用途
那么有了Rack能做什么呢?Rack充当了Ruby App Server和Ruby Web框架两者的胶水,实现关注点分离,开发者可以随时替换任一部分,例如Rails可以使用Unicorn,也可以使用Puma作为App Server,后续有更新的Server或Web框架都可以使用。之所以可以实现这点,就是因为Unicorn,Puma,Rails都是遵循Rack规范的。
每个Rack App都由Handler来调用(一般是Puma这种App Server提供),即由handler提供给我们编写的Rack App上下文(Web请求),由我们编写的Rack App来处理该请求。
最极简的流程就是Puma(Handler)获取到了HTTP请求,把请求交给Rack App处理(Handler调用Rack App的call),Puma(Handler)获取返回结果后响应给用户浏览器。下面的例子就展示了这样的流程。
一个简单的Rack App例子
code.rb
|
|
运行上述代码:ruby code.rb
:
一个简单的Web App就完成了,Rails和Sinatra这类Web框架都是基于Rack的扩展,Rack的设计对于中间件编写也同样方便,而且符合Rack规范的中间件可以在不同的Web框架中使用。
Rack除了是一个规范,还实现了一个Rack库,提供了一系列方便编写及运行Rack App的工具,包括一些简单的App Server(WEBrick,Thin等)、中间件和命令行工具rackup
等。
参考资料: