注:这里是根据网上的常见的 rack 例子更改
Rack 为使用 Ruby 开发 web 应用提供了一个最小的模块化和可修改的接口。用可能最简单的方式来包装 HTTP 请求和响应,它为 web 服务器,web 框架和中间件的 API 进行了统一并提纯到了单一的方法调用。
测试中 rack gem 版本为 1.6.4
module Rack
class A
def initialize(app)
@app = app # @app: Rack::B
@header_name = "X-A"
end
def call(env)
start_time = Time.now
status, headers, body = @app.call(env) # Rack::B 实例调用 call
request_time = Time.now - start_time
if !headers.has_key?(@header_name)
headers[@header_name] = "%0.6f" % request_time
end
[status, headers, body]
end
end
class B
def initialize(app)
@app = app # @app: Rack::C
@header_name = "X-test"
end
def call(env)
status, headers, body = @app.call(env) # Rack::C 实例调用 call
if !headers.has_key?(@header_name)
headers[@header_name] = 'yyyyyy'
end
[status, headers, body+['aaaaaa']]
end
end
class C
def call(env)
[200, {'Content-Type' => 'text/plain'}, ['hello world!']]
end
end
end
use Rack::A
use Rack::B
run Rack::C.new
~/test $ rackup
new B -------------
@app: #<Rack::C:0x007fa4b2ad4298>
------------------------------
new A-------------
@app: #<Rack::B:0x007fa4b2ad41f8>
------------------------------
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on localhost:9292, CTRL+C to stop
A call -------------
@app: #<Rack::B:0x007fa4b2ad41f8>
------------------------------
B call ----------------
@app: #<Rack::C:0x007fa4b2ad4298>
------------------------------
C call ----------
#<Rack::C:0x007fa4b2ad4298>
------------------------------
127.0.0.1 - - [08/Aug/2016:00:57:19 +0800] "GET / HTTP/1.1" 200 - 0.0041
A call -------------
@app: #<Rack::B:0x007fa4b2ad41f8>
------------------------------
B call ----------------
@app: #<Rack::C:0x007fa4b2ad4298>
------------------------------
C call ----------
#<Rack::C:0x007fa4b2ad4298>
------------------------------
127.0.0.1 - - [08/Aug/2016:00:57:20 +0800] "GET /favicon.ico HTTP/1.1" 200 - 0.0006
HTTP/1.1 200 OK
Content-Type: text/plain
X-test: yyyyyy
X-A: 0.000032
Transfer-Encoding: chunked
Connection: close
Server: thin
hello world!aaaaaa