Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.

Commit

Permalink
Merge pull request #40 from AusDTO/fix/force-https
Browse files Browse the repository at this point in the history
Force use of HTTPS by redirecting users
  • Loading branch information
maxious authored Sep 29, 2016
2 parents 6d44d3a + be6631c commit dc071b5
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
2 changes: 1 addition & 1 deletion dmutils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

import flask_featureflags

__version__ = '24.4.1'
__version__ = '24.4.2'
3 changes: 2 additions & 1 deletion dmutils/flask_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import flask_featureflags
from flask_featureflags.contrib.inline import InlineFeatureFlag
from . import config, logging, proxy_fix, request_id, formats, filters
from . import config, logging, force_https, proxy_fix, request_id, formats, filters
from flask import Markup, redirect, request, session
from flask.ext.script import Manager, Server
from flask_login import current_user
Expand Down Expand Up @@ -36,6 +36,7 @@ def init_app(
logging.init_app(application)
proxy_fix.init_app(application)
request_id.init_app(application)
force_https.init_app(application)

if feature_flags:
# Standardize FeatureFlags, only accept inline config variables
Expand Down
47 changes: 47 additions & 0 deletions dmutils/force_https.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# inspired by https://github.com/kennethreitz/flask-sslify
# Copyright (c) 2012, Kenneth Reitz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from flask import request, redirect


def init_app(app):
if app.config['DM_HTTP_PROTO'].lower() == "https":
app.before_request(redirect_to_ssl)
app.after_request(set_hsts_header)


def redirect_to_ssl():
"""Redirect incoming requests to HTTPS."""
# Should we redirect?
if request.url.startswith('http://'):
# redirect to HTTPS
url = request.url.replace('http://', 'https://', 1)
code = 301 # HTTP code 301 Moved Permanently
r = redirect(url, code=code)
return r


def set_hsts_header(response):
"""Adds HSTS header to each response."""
# Should we add STS header?
if request.is_secure:
response.headers.setdefault('Strict-Transport-Security', 'max-age=86400') # 1 day in seconds
return response
33 changes: 33 additions & 0 deletions tests/test_force_https.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from tests.helpers import BaseApplicationTest, Config
from dmutils import config, force_https
from flask import Flask


class TestForceHTTPSConfig(Config):
DM_HTTP_PROTO = "HTTPS"


class TestForceHTTPS(object):
config_object = TestForceHTTPSConfig()

def setup(self):
self.flask = Flask(
'test_app'
)
self.flask.config.from_object(self.config_object)
config.init_app(self.flask)
force_https.init_app(self.flask)
self.app = self.flask.test_client()

@self.flask.route('/some-page')
def some_page():
return 'Interesting content'

def test_http_view(self):
res = self.app.get('/some-page')
assert res.status_code == 301

def test_https_view(self):
res = self.app.get('/some-page', base_url="https://localhost")
assert res.status_code == 200
assert res.headers.get('Strict-Transport-Security')

0 comments on commit dc071b5

Please sign in to comment.