diff --git a/dockerfiles/nginx/proxito.conf b/dockerfiles/nginx/proxito.conf index 704404bfd7b..cd24b0ddbc3 100644 --- a/dockerfiles/nginx/proxito.conf +++ b/dockerfiles/nginx/proxito.conf @@ -58,6 +58,8 @@ server { add_header X-RTD-Domain $rtd_domain always; set $rtd_method $upstream_http_x_rtd_version_method; add_header X-RTD-Version-Method $rtd_method always; + set $rtd_redirect $upstream_http_x_rtd_redirect; + add_header X-RTD-Redirect $rtd_redirect always; } # Serve 404 pages here diff --git a/readthedocs/proxito/middleware.py b/readthedocs/proxito/middleware.py index e30dc12eb99..cdbb6908997 100644 --- a/readthedocs/proxito/middleware.py +++ b/readthedocs/proxito/middleware.py @@ -8,7 +8,7 @@ import logging from django.conf import settings -from django.shortcuts import render +from django.shortcuts import render, redirect from django.utils.deprecation import MiddlewareMixin from readthedocs.projects.models import Domain, Project @@ -83,6 +83,14 @@ def map_host_to_project_slug(request): # pylint: disable=too-many-return-statem project_slug = domain.project.slug request.cname = True log.debug('Proxito CNAME: host=%s', host) + + if domain.https and not request.is_secure(): + # Redirect HTTP -> HTTPS (302) for this custom domain + log.debug('Proxito CNAME HTTPS Redirect: host=%s', host) + resp = redirect('https://{}{}'.format(host, request.get_full_path())) + resp['X-RTD-Redirect'] = 'https' + return resp + return project_slug # Some person is CNAMEing to us without configuring a domain - 404. diff --git a/readthedocs/proxito/tests/test_middleware.py b/readthedocs/proxito/tests/test_middleware.py index ffa7297b87e..02cf1040822 100644 --- a/readthedocs/proxito/tests/test_middleware.py +++ b/readthedocs/proxito/tests/test_middleware.py @@ -38,6 +38,24 @@ def test_proper_cname(self): self.assertEqual(request.cname, True) self.assertEqual(request.host_project_slug, 'pip') + def test_proper_cname_https_upgrade(self): + domain = 'docs.random.com' + get(Domain, project=self.pip, domain=domain, https=True) + + for url in (self.url, '/subdir/'): + request = self.request(url, HTTP_HOST=domain) + res = self.run_middleware(request) + self.assertIsNotNone(res) + self.assertEqual(res.status_code, 302) + self.assertEqual( + res['Location'], + f'https://{domain}{url}', + ) + self.assertEqual( + res['X-RTD-Redirect'], + 'https', + ) + def test_proper_cname_uppercase(self): get(Domain, project=self.pip, domain='docs.random.com') request = self.request(self.url, HTTP_HOST='docs.RANDOM.COM')