class Rack::Domain

This Rack middleware allows to intercept requests and route them to different apps based on the domain (full, with subdomains and the TLD).

@example Using a regexp

# Match the 'lobster' subdomain.
use Rack::Domain, /^lobster\./, run: Rack::Lobster.new

@example Using a string

# Match only if the current domain is github.com:
use Rack::Domain, 'github.com', run: MyGitHubClone

@example Using an array of strings and regexps

use Rack::Domain, ['lobst.er', /^lobster\./], run: Rack::Lobster.new

@example Using an on-the-fly app build with a ‘Rack::Builder` block:

use Rack::Domain, /^api/ do
  use Rack::Logger
  run MyApi
end

Constants

VERSION

The version of this gem.

Public Class Methods

new(next_app, filter, opts = {}, &block) click to toggle source

Create a new instance of this middleware. Note that this method is the method called by ‘Rack::Builder#use`.

@param [#call] next_app The next app on the stack, filled automatically by

Rack when building the middlware chain.

@param [String, Regexp, Array<String, Regexp>] filter The filter used to,

well, filter the domain. If `filter` is a `String`, it will be matched as the
entire domain; if it's a regexp, it will be matched as a regexp. If it's
an array of strings and regexps, it will match if any of the elements of
the array matches the domain as specified above.

@param [Hash] opts An hash of options. @option opts [#call, nil] :run The Rack app to run if the domain matches the

filter. If you don't want to pass a ready application, you can pass a
block with `Rack::Builder` syntax which will create a Rack app on-the-fly.

@raise [ArgumentError] if both a building block and an app to run were

passed to this function.
# File lib/rack/domain.rb, line 41
def initialize(next_app, filter, opts = {}, &block)
  if opts[:run] && block_given?
    fail ArgumentError, 'Pass either an app to run or a block, not both'
  end

  @next_app = next_app
  @filter = filter
  @app_to_run = opts[:run]
  @dsl_block = block
end

Public Instance Methods

call(env) click to toggle source

The ‘call` method as per the Rack middleware specification. @param [Hash] env The environment passed around in the middlware chain.

# File lib/rack/domain.rb, line 54
def call(env)
  @domain = Rack::Request.new(env).host
  app = domain_matches? ? app_or_dsl_block : @next_app
  app.call(env)
end

Private Instance Methods

app_or_dsl_block() click to toggle source

Return the app that was specified to be run if the domain matches or, if the app was specified on-the-fly with a builder block, return a new app created with that block (and ‘Rack::Builder`). @return [#call]

# File lib/rack/domain.rb, line 66
def app_or_dsl_block
  @app_to_run || Rack::Builder.new(&@dsl_block)
end
domain_matches?() click to toggle source

Return ‘true` if the domain of the current request matches the given `@filter`, `false` otherwise. @raise [ArgumentError] if the filter or array of filters aren’t regexps or

strings.

@return [Boolean]

# File lib/rack/domain.rb, line 75
def domain_matches?
  # Force the filter to be an array.
  @filter = [@filter] unless @filter.is_a?(Array)

  # Check if any of the elements of the `@filter` array matches the domain.
  # The matching test is done based on the element's type.
  @filter.any? do |flt|
    if flt.is_a?(Regexp)
      flt =~ @domain
    elsif flt.is_a?(String)
      flt == @domain
    else
      fail ArgumentError, 'The filters must be strings or regexps'
    end
  end
end