Rack的用法,以及rails的启动加载顺序 - tianlu1677/tianlu1677.github.io GitHub Wiki

1. 什么是rack

Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.

2. 启动方式

2.1 必须要满足这三个条件,才可以启动一个服务

  • The HTTP response code
  • A Hash of headers
  • The response body, which must respond to each 可以有这两种写法:
# my_rack_app.rb
require 'rack'
app = Proc.new do |env|
    ['200', {'Content-Type' => 'text/html'}, ['A barebones rack app.']]
end
Rack::Handler::WEBrick.run app

或者使用 rackup 命令

# config.ru
run Proc.new { |env| ['200', {'Content-Type' => 'text/html'}, ['get rack\'d']] }

$ rackup config.ru ## 这里的 rackup就是只是启动而已

require "rack"
Rack::Server.start

3.Rack 的模块 Rack::Builder

它会将rack application 以及 middlewares 封装成一个 单独的rack application。这样就可以单独调用了。

3.1 Rack::Builder#run

infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, [env.inspect]]}
Rack::Handler::WEBrick.run infinity, :Port => 9292

||

infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, [env.inspect] ]}
builder = Rack::Builder.new
builder.run infinity
Rack::Handler::WEBrick.run builder, :Port => 9292

|| 这种把内容方法block里面

infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, [env.inspect] ]}
builder = Rack::Builder.new do
  run infinity
end
Rack::Handler::WEBrick.run builder, :Port => 9292

3.2 Rack::Builder#use

这use是用于把中间件加载到当前的rack application中。

infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, [env.inspect] ]}
builder = Rack::Builder.new do
  use Rack::CommonLogger
  run infinity
end
Rack::Handler::WEBrick.run builder, :Port => 9292

3.3 Rack::Builder#map

Rack::Builder#map mounts a stack of rack application/middlewares the specified path or URI and all the children paths under it. 挂载不同的URL或者中间件的路径。

infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, env.inspect]}
builder = Rack::Builder.new do
  use Rack::CommonLogger

  map '/' do
    run infinity
  end

  map '/version' do
    run Proc.new {|env| [200, {"Content-Type" => "text/html"}, ["infinity 0.1"] ] }
  end
end
Rack::Handler::WEBrick.run builder, :Port => 9292

或者采用嵌套的形式

infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, env.inspect]}
builder = Rack::Builder.new do
  use Rack::CommonLogger

  map '/' do
    run infinity
  end

  map '/version' do
    run Proc.new {|env| [200, {"Content-Type" => "text/html"}, ["infinity 0.1"] ] }
  end

  map '/version/last' do
    run Proc.new {|env| [200, {"Content-Type" => "text/html"}, ["infinity beta 0.0"] ] }
  end
end
Rack::Handler::WEBrick.run builder, :Port => 9292

而一般会封装在一个 .ru文件中,所有相关的配置。不会采用Rake::Builder,而用rackup这个命令。

rackup infinity.ru

# infinity.ru
infinity = Proc.new {|env| [200, {"Content-Type" => "text/html"}, env.inspect]}
use Rack::CommonLogger
map '/' do
  run infinity
end
map '/version' do
  map '/' do
    run Proc.new {|env| [200, {"Content-Type" => "text/html"}, ["infinity 0.1"]] }
  end
  end
end

或者是这样

config_file = File.read(config)
rack_application = eval("Rack::Builder.new { #{config_file} }")
And then rackup supplies rack_application to the respective webserver :

server.run rack_application, options

4.rails 启动顺序

TODO 解构


参考: