0

对于我的一个 ruby​​ 应用程序,我需要服务器根据子域路由请求。有很多方法可以使用其他 gem 来做到这一点,但我决定制作自己的“中间件”。此代码根据请求的目的地运行应用程序。

配置.ru

require './subdomain'
require './www'

run Rack::Subdomain.new([
  {
    :subdomain => "test", 
    :application => Sinatra::Application
  }
]);

子域.rb

module Rack
  class Subdomain
    def initialize(app)
      @app = app
    end

    def call(env)
      @app.each do |app|
        match = 'test'.match(app[:subdomain])
        if match
          return app[:application].call(env)
        end
      end
    end
  end
end

我的问题是如何修改此工作代码以使其工作完全相同,但通过如下代码调用它:

run Rack::Subdomain do
  map 'www' do
    Example::WWW
  end

  map 'api' do
    Example::API
  end
end

使用建议的代码:

配置.ru

require './subdomain'
require './www'

run Rack::Subdomain.new do |x|
  x.map 'test' do
    Sinatra::Application
  end
end

子域.rb

module Rack
  class Subdomain
    def initialize(routes = nil)
      @routes = routes
      yield self
    end

    def map(subdomain)
      @routes << { subdomain: subdomain, application: yield }
    end

    def call(env)
      @routes.each do |route|
        match = 'test'.match(route[:subdomain])
        if match
          return route[:application].call(env)
        end
      end
    end
  end
end
4

1 回答 1

-1

您调用上面的“工作代码”,但它似乎根本没有检测到子域,而是将其连接到文字“测试”。无论如何,您可以通过创建一个 map 方法来实现类似于您想要的模式,该方法将条目添加到您的子域-> 应用程序路由列表中。我已将您的重命名为@app@routes因为它是路由的哈希,而不是应用程序引用。

module Rack
  class Subdomain
    def initialize(routes = [])
      @routes = routes
      yield self if block_given?
    end

    def map(subdomain)
      @routes << { subdomain: subdomain, application: yield }
    end

    def call(env)
      @routes.each do |route|
        match = 'test'.match(route[:subdomain])
        if match
          return route[:application].call(env)
        end
      end
    end
  end
end

rsd = Rack::Subdomain.new do |x|
  x.map 'www' do
    Example::WWW
  end

  x.map 'api' do
    Example::API
  end
end

run rsd
于 2013-03-10T19:20:29.667 回答