您的位置:首页 > 其它

Rack相关知识梳理(三)

2022-05-12 00:24 204 查看
Rack为编写Web应用以及Web框架提供了很多便利的工具,那么这一节,我们实现一个最简单的Web框架。   一、Web框架应该具备什么功能
  • 对request和response的存取
  • 路由:根据不同URL执行不同程序
  • 能够处理cookies
  • 能够存取session
  • 能够生成日志
  • ......
  看上去挺麻烦的,是吧?其实,则不然 前面我们已经知道Rack::Request和Rack::Response这两个类可以用来处理request和 response,那么我们该如何实现路由呢?Rack提供Rack::URLMap类来处理路由,我们这里可以不直接使用这个类,如果大家仔细看Rack::Builder的实现,大家会发现这个类提供了一个map方法以及generate_map方法: map
def map(path, &block)
@map ||= {}
@map[path] = block
end
generate_map
def generate_map(default_app, mapping)
mapped = default_app ? {'/' => default_app} : {}
mapping.each { |r,b|
mapped[r] = self.class.new(default_app, &b).to_app
}
URLMap.new(mapped)
end
路由的作用其实就是根据URL请求的路径去调用对应的程序,因此map方法它接受路径path和 对应的程序&block,然后用hash保存其对应关系generate_map这个方法是在to_app中调用的,它主要通过URLMap建立起路由和所执行应用程序的关系。
def to_app
app = @map ? generate_map(@run, @map) : @run
fail "missing run or map statement" unless app
app = @use.reverse.inject(app) { |a,e| e[a] }
@warmup.call(app) if @warmup
app
end
前面我们知道to_app方法是为了组合中间件以及应用程序的,通过这段代码我们可以看出来, 在组合中间件之前需要先根据路由找到真正的run,然后再组装对应的中间件。   二、一个简单的Web框架 下面是一个简单的web框架,具备对request、response的处理并且具有路由、日志功能。
require 'rack'
app = Rack::Builder.new {
use Rack::ContentLength
map '/hello' do
use Rack::CommonLogger
map '/user1' do
run lambda {|env|
[200, {"Content-type" => "text/html"}, ["from user1", "SCRIPT_NAME=#{env["SCRIPT_NAME"]}", "PATH_INFO=#{env["PATH_INFO"]}"]]
}
end

map '/everyone' do
run lambda {|env| [200, {"Content-type" => "text/html"},
["from everyone", "SCRIPT_NAME=#{env["SCRIPT_NAME"]}", "PATH_INFO=#{env["PATH_INFO"]}"]]
}
end

map '/' do
run lambda {|env| [200, {"Content-type" => "text/html"},
["from hello catch all", "SCRIPT_NAME=#{env["SCRIPT_NAME"]}", "PATH_INFO=#{env["PATH_INFO"]}"]]
}
end
end

map '/' do
run lambda {|env| [200, {"Content-type" => "text/html"}, ["root"]]
}
end
}.to_app
Rack::Handler::WEBrick.run app, :Port => 3000
通过上面代码可以看出来:
  • map是可以嵌套的
  • 可以对不同的路由使用不同的中间件组合

 

三、rackup

前面我们的代码中最后一行总是这样写的:

Rack::Handler::WEBrick.run xxx, :Port => 3000

这样做写死了所要用的服务器,不灵活。

Rack提供了rackup命令,允许我们用一个配置文件去执行我们的应用程序,rackup使用很简单,我们只需要提供一个后缀为.ru的配置文件即可,然后运行 rackup xxx.ru就ok了,我们把 前面代码改为:

map '/hello' do
map '/user1' do
run lambda {|env| [200, {"Content-type" => "text/html"}, ["from user1",
"SCRIPT_NAME=#{env["SCRIPT_NAME"]}", "PATH_INFO=#{env["PATH_INFO"]}"]]
}
end

map '/everyone' do
run lambda {|env| [200, {"Content-type" => "text/html"},
["from everyone", "SCRIPT_NAME=#{env["SCRIPT_NAME"]}", "PATH_INFO=#{env["PATH_INFO"]}"]]
}
end

map '/' do
run lambda {|env| [200, {"Content-type" => "text/html"},
["from hello catch all", "SCRIPT_NAME=#{env["SCRIPT_NAME"]}", "PATH_INFO=#{env["PATH_INFO"]}"]]
}
end
end

map '/' do
run lambda {|env| [200, {"Content-type" => "text/html"}, ["root"]]
}
end
保存上述代码到config.ru文件然后运行 rackup config.ru即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: