Skip to content

Instantly share code, notes, and snippets.

@noma4i
Forked from johnthethird/customdomain.rb
Created October 9, 2022 08:00
Show Gist options
  • Save noma4i/b79891639bfb23e462f38e9deb775ecf to your computer and use it in GitHub Desktop.
Save noma4i/b79891639bfb23e462f38e9deb775ecf to your computer and use it in GitHub Desktop.
rack middleware to resolve a custom domain to an original subdomain in a multi-tenant application
require 'net/dns/resolver'
# Custom Domain
#
# Require net-dns gem
#
# A Rack middleware to to resolve the custom domain to original subdomain
# for your multi telent application.
#
# It's all transperant to your application, it performs cname lookup and
# overwrite HTTP_HOST if needed
#
# www.example.org => example.myapp.com
#
# Credit: Inspired by http://codetunes.com/2009/04/17/dynamic-cookie-domains-with-racks-middleware/
class CustomDomain
@@cache = {}
def initialize(app, default_domain)
@app = app
@default_domain = default_domain
end
def call(env)
host, port = env["HTTP_HOST"].split(':')
# modify Environment variable HTTP_HOST if custom domain is found
if custom_domain?(host)
domain = cname_lookup(host)
env['HTTP_X_FORWARDED_HOST'] = [host, domain].join(', ')
logger.info("CustomDomain: mapped #{host} => #{domain}")
end
@app.call(env)
end
def custom_domain?(host)
host !~ /#{@default_domain.sub(/^\./, '')}/i
end
def cname_lookup(host)
unless @@cache[host]
Net::DNS::Resolver.new.query(host).each_cname do |cname|
@@cache[host] = cname if cname.include?(@default_domain)
end
end
@@cache[host]
end
private
def logger
RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment