ruby rackup:是否可以以编程方式从另一个映射中添加映射?

时间:2016-07-08 14:30:51

标签: ruby web-services webserver rack

我有一个.ru文件,可以设置没有问题的映射(下面的'注册'映射)。

但是我希望服务能够通过点击URL来注册自己,所以我希望能够在其他映射中动态添加新的映射。

以下代码可以工作。我做错了什么,这可能吗?

谢谢!

map '/register' do
  run Proc.new { |env|
    # inside of register i want to add another mapping.
    # obviously 'bar' would be a value read out of env
    map '/bar' do
      run Proc.new{ |env| ['200', { 'Content-Type' => 'text/html' },'bar' }
    end

    [ '200', {'Content-Type' => 'text/html'}, "registered"]
  }
end

2 个答案:

答案 0 :(得分:1)

我认为没有办法使用map在事后添加路线。另一种方法是使用Rack::URLMap来定义您的应用。您需要维护自己的已注册路由列表(作为哈希),并在每次向哈希添加新路由时调用Rack::URLMap#remap

url_map = Rack::URLMap.new
routes = {
  "/register" => lambda do |env|
    routes["/bar"] = lambda do |env|
      [ "200", {"Content-Type" => "text/plain"}, ["bar"] ]
    end

    url_map.remap(routes)

    [ "200", {"Content-Type" => "text/plain"}, ["registered"] ]
  end
}

url_map.remap(routes)
run url_map

请注意,您可以只使用哈希,但URLMap提供了一些很好的便利,包括404处理。它实际上是一个非常好的小班,worth reading如果你还有五分钟的时间。

如果你如此倾向,你可以把它变成一个整洁的小班:

class Application
  def initialize
    @routes = {}
    @url_map = Rack::URLMap.new

    register_route "/register" do |env|
      # When "/register" is requested, register the new route "/bar"
      register_route "/bar" do |env|
        [ 200, {"Content-Type" => "text/plain"}, ["bar"] ]
      end
      [ 200, {"Content-Type" => "text/plain"}, ["registered"] ]
    end
  end

  def call(env)
    @url_map.call(env)
  end

  private
  def register_route(path, &block)
    @routes[path] = block
    @url_map.remap(@routes)
  end
end

run Application.new

答案 1 :(得分:0)

根据https://rack.github.io/,"要使用Rack,请提供" app":响应调用方法的对象,将环境哈希作为参数,并返回包含三个元素的数组:

  • HTTP响应代码
  • 哈希标题
  • 响应正文,必须回复each"

您的第三个元素不会回复each。也许将它包装在一个数组中?