[Django]-Django Project can't force Google Appengine to redirect to https

1πŸ‘

βœ…

All the answers here helped guide me on the right path. This is the final app.yaml setup that worked for my project after a million attempts. (I was also trying to reduce appengine costs by limiting the resources

# [START runtime]
vm: true
runtime: custom
service: backend-dev

manual_scaling:
   instances: 1

resources:
  cpu: .5
  memory_gb: 0.6
  disk_size_gb: 10

handlers:

- url: /static
  static_dir: static

- url: /.*
  script: myapplication.wsgi.py
  secure: always

# [END runtime]
πŸ‘€ozhou

3πŸ‘

Just add a secure parameter to the app.yaml file.

handlers:
- url: /*
  script: anyfile.py
  secure: always

See Configuring Secure URLs in app.yaml

1πŸ‘

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

πŸ‘€GAEfan

Leave a comment