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

Matt Murphy Konstantin Haase
Matt Murphy

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.

Konstantin Haase
Owner

This can already be done with Rack::URLMap.

Konstantin Haase 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. Matt Murphy
This page is out of date. Refresh to see the latest.
1  README.rdoc
View
@@ -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
55 lib/rack/contrib/subdomain_router.rb
View
@@ -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
43 test/spec_rack_subdomain_router.rb
View
@@ -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.