As Bravin said, a simple method is to add secure: always to app.yaml. However, if you care about consistent subdomains (e.g., always going to the www. address), then you would want to write your own middleware to redirect to 'https://www....`
Consistent subdomains is an SEO thing. Search engines can count the naked domain and the www. domain as distinct addresses. Also, some SSL certificates only cover one subdomain (i.e. www.) and not the naked domain.
If you write your own middleware, make sure you exempt tasks, crons, backends, etc., or they might get stuck returning 301s. Also exempt your localhost requests for development.
Also, there is still a small percentage of users with older browsers or operating systems that cannot be served SSL using the SNI protocol. What do you do with those? In this example, we still serve them secure content, using the appspot.com certificate.
Example middleware:
from django.http import HttpResponsePermanentRedirect import os import logging class ForceHttps(object): ''' We want all requests to go to https://www.{mysite}.com except: Cron, Taskqueue, backend jobs, dev server test this against secure: always in app.yaml In this example, we redirect non-SNI compatible browsers to the secure appspot.com address ''' def process_request(self, request): user_agent = request.META.get('HTTP_USER_AGENT', 'fake') if ( 'AppEngine-Google' in user_agent or 'mybackendmodule' in request.META.get('CURRENT_MODULE_ID') or 'dot-appname' in request.META.get('HTTP_HOST') or os.environ.get('SERVER_SOFTWARE', '').lower().startswith('devel') ): return None # for non-SNI SSL browsers, we send to appspot domain: if ( ((('Windows NT 5.1' in user_agent) or ('Windows XP' in user_agent)) and (('MSIE' in user_agent) or ('Safari' in user_agent) or ('Chrome' in user_agent))) or # XP with most browsers (('MSIE 6' in user_agent) or ('MSIE 5' in user_agent)) or # any version of IE6 or 5 ((('Windows NT 6.1' in user_agent) or ('Windows NT 6.2' in user_agent)) and ('webDAV' in user_agent)) or # IE7 or 8 with webDAV (('Android 2.' in user_agent) or ('Android 1.' in user_agent)) ): # android 2.x logging.info('Redirecting to appspot. SNI incompatibility detected: ' + user_agent ) return HttpResponsePermanentRedirect("https://{appname}.appspot.com" + request.META.get('PATH_INFO')) # for SNI compatible browsers: if request.META.get('HTTPS') == 'off' or 'www' not in request.META.get('HTTP_HOST') : return HttpResponsePermanentRedirect("https://www.{mysite}.com" + request.META.get('PATH_INFO')) return None
Be sure to add 'path_to.my_middleware.ForceHttps' to MIDDLEWARE_CLASSES in SETTINGS.py