Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

simple wildcard subdomain routing table support #20

Closed
wants to merge 1 commit into from

2 participants

@mmmurf

Hello, I needed this functionality and wrote this simple middleware.

Please let me know if you decide not to accept it a few suggestions to improve its chances :)

included a simple spec and usage notes as well.

@rkh
Owner

This can already be done with Rack::URLMap.

@rkh rkh closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 1, 2010
  1. @mmmurf
This page is out of date. Refresh to see the latest.
View
1  README.rdoc
@@ -48,6 +48,7 @@ interface:
* Rack::ResponseHeaders - Manipulates response headers object at runtime
* Rack::SimpleEndpoint - Creates simple endpoints with routing rules, similar to Sinatra actions
* Rack::TryStatic - Tries to match request to a static file
+* Rack::SubdomainRouter - Lets you set up regex based routing for subdomain handling
=== Use
View
55 lib/rack/contrib/subdomain_router.rb
@@ -0,0 +1,55 @@
+module Rack
+ #
+ # A Rack middleware for handling subdomains using a simple regex
+ # routing table. Useful for handling wildcard subdomains.
+ #
+ # If a request matches one of the subdomains defined by your regex,
+ # it is passed to the app defined in the routing table.
+ #
+ # Otherwise, the request is just handled by your main app.
+ #
+ # e.g.:
+ #
+ # sub1 = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from sub1!"]] }
+ # sub2 = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from sub2!"]] }
+ # www = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from www!"]] }
+ #
+ # app = Rack::Builder.new do
+ #
+ # use Rack::SubdomainRouter, "test.com",
+ # {
+ # /^(www\.)?(sub1)/ => sub1,
+ # /^sub2/ => sub2,
+ # /^www/ => www
+ # }
+ #
+ # run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from default!"]] }
+ # end
+ #
+ # MIT-License - Matt Murphy
+ #
+ class SubdomainRouter
+ def initialize(app, base_url, routes)
+ @app = app
+ @routes = routes
+ @base_url = base_url
+ end
+
+ def call(env)
+ subdomain = env['SERVER_NAME'].gsub(@base_url, '').strip.downcase
+ match = nil
+ @routes.keys.each do |r|
+ if subdomain =~ r
+ match = r ; break
+ else
+ match = nil
+ end
+ end
+ if match
+ @routes[match].call(env)
+ else
+ @app.call(env)
+ end
+ end
+ end
+end
View
43 test/spec_rack_subdomain_router.rb
@@ -0,0 +1,43 @@
+require 'test/spec'
+require 'rack/builder'
+require 'rack/mock'
+require 'rack/contrib/subdomain_router'
+
+context "Rack::Subdomain_Router" do
+ specify "routes to proper subdomain" do
+
+ sub1 = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from sub1!"]] }
+ sub2 = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from sub2!"]] }
+ www = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from www!"]] }
+
+ app = Rack::Builder.new do
+
+ use Rack::SubdomainRouter, "test.com",
+ {
+ /^(www\.)?(sub1)/ => sub1,
+ /^sub2/ => sub2,
+ /^www/ => www
+ }
+
+ run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["hi from default!"]] }
+ end
+
+
+ response = Rack::MockRequest.new(app).get('http://sub1.test.com/')
+ response.body.should.equal('hi from sub1!')
+
+ response = Rack::MockRequest.new(app).get('http://www.sub1.test.com/')
+ response.body.should.equal('hi from sub1!')
+
+ response = Rack::MockRequest.new(app).get('http://www.test.com/')
+ response.body.should.equal('hi from www!')
+
+ response = Rack::MockRequest.new(app).get('http://sub2.test.com/')
+ response.body.should.equal('hi from sub2!')
+
+ response = Rack::MockRequest.new(app).get('http://test.com/')
+ response.body.should.equal('hi from default!')
+
+ end
+
+end
Something went wrong with that request. Please try again.