Forums

A perfectionist's solution to naked domains and SSL

I thought I'd document this here in the hope that it might help someone else.

I wanted to redirect visitors from the 'naked' (i.e. no-www) version of my domain to the www version, and also ensure that all access to my application went over HTTPS. The issue of canonicalization also had to be considered, to ensure that there weren't effectively two copies of the application on the Internet, dividing PageRank between them.

In other words, all these URLs would be redirected to https://www.foodomain.co.uk/query/string:

http://www.foodomain.co.uk/query/string
http://foodomain.co.uk/query/string
https://foodomain.co.uk/query/string

The first case is easily taken care of by forcing HTTPS within whatever framework you're using, and the second can be sorted with a domain redirection service as described in the Help pages.

However, the third case is a bit different - the redirection service won't have your SSL certificate installed, so your users will see nasty 'certificate warning errors' when they're sent through the redirect.

You can get around this by putting the redirection logic on PA, as long as two things hold true: your SSL certificate is valid for your root domain as well as the www subdomain, and you've asked the PA team to install your cert on both your with-www and naked-domain applications.

  1. Point your naked/root domain either to your pythonanywhere.com subdomain (via a ALIAS record or similar) or to its IP (via an A record) if your DNS provider can't do root domain aliases.
  2. Create an app for foodomain.co.uk without the www, selecting 'Manual config'.
  3. Set up your wsgi.py to look something like the following

def application(environ, start_response):
    server_name = environ.get("SERVER_NAME")
    path_info = environ.get("PATH_INFO", "")
    target_url = "https://www.{}{}".format(server_name, path_info)
    start_response("301 Moved Permanently", [("Location", target_url)])
    return ["<html><head></head><body><a href='{0}'>{0}</a></body></html>".format(target_url)]

You could also put this in a file somewhere in your home directory, and then do:

import sys
path = '/home/username/path/to/file/'
if path not in sys.path:
    sys.path.append(path)
from filename import application

This way, users that visit your naked domain are redirected to the www subdomain, the query string is preserved across the redirect, they're seamlessly shifted onto HTTPS if needed and their browser won't bleat about SSL certificate errors.

What's more, as the redirects are HTTP 301s no PageRank is lost as Google's spiders will only see https://www.foodomain.co.uk as containing any content.