This blog has existed under a few domain names: workingconfig.com, thornelaboratories.net, and, now, thornelabs.net. workingconfig.com 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. However, thornelaboratories.net did exist for a longer period of time, and it had URLs I wanted to keep alive.
I can easily host thornelaboratories.net and thornelabs.net from the same webserver on a single VM - I never needed more resources to serve static content.
The configuration redirects for thornelaboratories.net 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 thornelaboratories.net and thornelabs.net in the same git repository, and I wanted to separate the two domains even more; I wanted to host thornelaboratories.net 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 thornelaboratories.net redirects, hosting the redirect service on Google App Engine would easily fit within the limits of App Engine’s free tier.
Prerequisites
This post assumes the following:
- You are familiar with Google Cloud Platform (GCP) and have already created a GCP Project
- You have installed the Google Cloud SDK
- You have authenticated the
gcloud
command against your Google Account
Create a GCP Project
If you have not yet created a GCP Project, follow these steps:
- Open a web browser, and create or log in to a Google Account
- Navigate to the GCP Console
- If this is your first GCP Project, you will be prompted to create a GCP Project. Each Google Account gets $300 in credit to use within 12 months towards GCP. You are required to enter a credit card to create a GCP Project, but it will not be charged until the $300 credit is consumed or 12 months expire.
- If this is a new GCP Project, you will need to enable the Compute Engine API by navigating to the Compute Engine section of the GCP Console and wait for initialization to complete
Install the Google Cloud SDK
If you have not yet installed the Google Cloud SDK, follow the instructions here.
Authenticate gcloud
Once you have created a GCP Project and installed the Google Cloud SDK, the last step is to authenticate the gcloud
command to your Google Account. Open your terminal application and run the following command:
gcloud auth login
A web page will open in your web browser. Select your Google Account and give it permission to access GCP. Once completed, you will be authenticated and ready to move forward.
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
handlers:
- url: /.*
script: main.app
Create main.py
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 in the else blocks in method get in 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 main.py, copy and paste the code below, and make the following modifications:
- In the domain variable, change the value to match your domain name with the correct HTTP protocol.
- 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 just the path portion of the new URL you want to redirect to.
All redirects will be 301 redirects. This can be changed to a 302 redirect by changing self.redirect(url, permanent=True) in the code below to self.redirect(url, permanent=False).
import webapp2
import logging
from urlparse import urlparse
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 the value of the path key from the urls dictionary
return urls[path]
else:
return False
class MainPage(webapp2.RequestHandler):
def get(self):
url = get_redirect_url(self.request.url)
if url:
# Concatenate the new domain with the redirect path
url = domain + url
# Redirect to the new URL with a 301 redirect
self.redirect(url, permanent=True)
else:
self.error(404)
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),
])
# The domain with protocol to redirect to
domain = "https://thornelabs.net"
# Path => URL to redirect to
urls = {
'/': ('/'),
'/index.html': ('/index.html'),
'/post/example-post-1.html': ('/post/example-post-1.html'),
'/post/example-post-2.html': ('/post/example-post-2.html'),
}
Deploy to App Engine
With app.yaml and main.py 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 https://your-project-id.appspot.com. 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 https://your-project-id.appspot.com. 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 http://old-domain-example.com/post/example-post-1.html in your web browser and have it redirect to http://new-domain-example.com/post/example-post-1.html.