Use Google App Engine and Python for Inexpensive Domain Redirects

Monday, March 6, 2017

This blog has existed under a few domain names:,, and, now, didn’t exist for very long, and never had many - if any - backlinks to it; it didn’t make sense to keep those URLs alive., on the other hand, did exist for a longer period of time, and it had enough URLs I wanted to keep alive.

I can easily host and from the same webserver on a single VM - I never needed more resources to serve static content.

The configuration redirects for lived in its own VirtualHost when I ran Apache, and then its own Server Block when I migrated to nginx. This worked well, but I was managing the nginx configurations for and in the same git repository, and I wanted to seperate the two domains even more; I wanted to host somewhere else and not have to think about it any more, but I didn’t want to create another VM for it because it would be a waste of resources to redirect so little traffic. I wanted to host it somewhere new and different, and spend as little money as possible.

Then I found Max Laumeister’s blog post on how to use Google App Engine as a free redirect server. This was exactly what I was looking for, and, given how little traffic redirects, hosting the redirect service on Google App Engine would easily fit within the limits of App Engine’s free tier.

Prerequisites and Authentication

This post assumes the following:

  • You are familiar with Google Cloud Platform and have already created a Google Cloud Project
  • You have installed the Google Cloud SDK. If you haven’t already installed it, follow the instructions here.

Finally, make sure gcloud is authenticated against Google Cloud Platform:

gcloud auth login

A web page will open in your web browser. Select and give permission to your Google account to access Google Cloud Platform, and you should be authenticated.

Create a Directory

Next, create a directory somewhere on your workstation to store your Google App Engine application:

mkdir ~/Development/domain-redirect/app-engine

Change into that directory:

cd ~/Development/domain-redirect/app-engine

The remainder of this post will assume you are working inside of this directory.

Create app.yaml

Google App Engine typically requires two files: app.yaml and an application file written in Python, Golang, Java, or PHP - in this case it’s going to be Python.

app.yaml provides the necessary configuration to run your application. There are a lot of different parameters that can exist in app.yaml. Those parameters might differ based on the programming language used. For this post, Python will be used, and you can find all the available Python parameters here.

Create file app.yaml with the following contents:

runtime: python27
api_version: 1
threadsafe: yes

- url: /.*


Next, you need the Python application file.

Most of the following code comes from Max’s post, but I have made some modifications. I wanted to be very exact in what URLs I was redirecting; I did not want a catch-all redirect. So, I removed the DEFAULT_URL variable and redirection code originally found under the else blocks in method get under the MainPage class. If you prefer to have a catch-all redirect, refer to the aforementioned code block in Max’s post.

For the following code to meet your needs, create file, and, in the urls dictionary, replace all of the key value pairs to match the redirects you need in place. Replace each key with just the path portion of the old URL you want to keep alive. Then replace each value with the exact new URL - domain and path - you want to redirect to. You more than likely want to keep the 301 redirect, but it can be changed if needed.

import webapp2
import logging
from urlparse import urlparse

# Path => URL to redirect to, redirect type (301 is permanent, 302 is temporary)
urls = {
    '/': ('', '301'),
    '/index.html': ('', '301'),
    '/post/example-post-1.html': ('', '301'),
    '/post/example-post-2.html': ('', '301'),

def get_redirect_url(url):
    scheme, netloc, path, params, query, fragment = urlparse(url)

    # Fix empty paths to be just '/' for consistency
    if path == '':
        path = '/'

    # Check if we have a mapping for this url
    if path in urls:
        return urls[path]
        return None, None

class MainPage(webapp2.RequestHandler):
    def get(self):
        url, perm = get_redirect_url(self.request.url)

        if url:
            self.redirect(url, permanent=True)

            logging.error('Unable to redirect this url: ' + self.request.url);

            self.response.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
            self.response.write('<title>404 Not Found</title>')
            self.response.write('<h1>Not Found</h1>')
            self.response.write('<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>')

app = webapp2.WSGIApplication([
    ('/.*', MainPage),

Deploy to App Engine

With app.yaml and saved, you are ready to deploy your Google App Engine application.

Assuming gcloud is already pointed at the Google Cloud Project you want to deploy to, verify with gcloud config list project, run the following command:

gcloud app deploy

The command will output the appspot URL your application will be deployed to and ask if you want to continue. Typically, the appspot URL is This is also a useful self-check to make sure you are not deploying your application to the wrong Google Cloud Project. If everything looks okay, type Y and Enter to deploy your application. After a few seconds, the application should be deployed.

Setup DNS

At this point, your application is deployed under URL Unless your website used that as its old domain name, you probably want to setup a custom domain that uses your actual old domain name.

The App Engine section of the Google Cloud Console can be used to do this. Go here and follow the instructions to configure your custom domain.

Once that is complete and DNS has had time to propagate, you should be able to navigate to in your web browser and have it redirect to


Generic 301 Redirection Script for Google App Engine

comments powered by Disqus