Modify Rack App

回眸只為那壹抹淺笑 提交于 2019-12-11 15:36:31

问题


For one of my ruby applications i need the server to route requests based on the subdomain. There are ways to do this using other gems but i decided to make my own "middleware". This code runs applications based on where the request is going to.

config.ru

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

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

subdomain.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

My question is how can i modify this working code to work exactly the same but have it called by code that looks like this:

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

  map 'api' do
    Example::API
  end
end

With suggested code:

config.ru

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

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

subdomain.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

回答1:


You call the above "working code" but it doesn't seem to detect the subdomain at all, but wires it to the literal 'test'. At any rate, you can implement a pattern similar to what you want by making a map method which adds entries to your list of subdomain->application routes. I've renamed your @app to @routes since it is a hash of routes, not an application reference.

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


来源:https://stackoverflow.com/questions/15325002/modify-rack-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!