Handling Subdomain Routes with AppEngine
I've been using GAE-Boilerplate for several projects including the code here on StackGeek. GAEB uses webapp2 for it's application framework. Recently, while trying to solve a security concern with utter.io, I went in search of a way to route subdomains to different handlers.
Subdomain Handling
Webapp2 provides a method called DomainRoute which takes a subdomain as an argument and uses it to match a set of routes you pass to it. Here's a snippet of that in action:
routes = [
# handle specific subdomain/hostname
DomainRoute(config.subdomain_hostname, [
Route('/', handler='handlers.PageHandler:subdomain', name='pages-subdomain'),
]),
# handle other hostnames and domains
Route('/', handler='handlers.PageHandler:root', name='pages-root'),
]
Try It Out
You can clone my example repo and add it to AppEngine Launcher to test the code. Check out the code locally by doing the following:
git clone git://github.com/kordless/webapp2-starter.git
You'll also need to modify your local hosts file for testing. Add the following to the bottom of your /etc/hosts file:
sublocalhost 127.0.0.1
Add the new project by going to File..Add Existing Application and browsing to the directory where you checked it out. Be sure to set the port to 8282 if you want to use the links I provide below.
Click on add. Click on the run button to start the app. You should now be able to hit the following urls:
Notice you get different results for the two pages.
Production Configuration
For this to work in production on AppEngine, you'll need to add the full subdomain+domain to Google Apps. In the screenshot below, I've added a subdomain oi.utter.io to the utter.io domain I configured the first time through domain setup for my AppEngine project.
Now I'm in production, my config file looks like this:
# config file
if os.environ['SERVER_SOFTWARE'].startswith('Dev'):
subdomain_hostname = 'sublocalhost'
else:
subdomain_hostname = 'oi.utter.io'
With this technique I've been able to keep the code in a single repository, deployed to a single AppEngine project, yet serve two distinct subdomains. Very handy!