ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Rack相关知识梳理(三)

2022-05-12 00:31:06  阅读:219  来源: 互联网

标签:map run app 知识 梳理 env end Rack


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即可。

标签:map,run,app,知识,梳理,env,end,Rack
来源: https://www.cnblogs.com/alalazy/p/16260625.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有