Skip to content

Commit 5faf178

Browse files
authored
Merge pull request #1332 from makeabilitylab/1236-https-scheme-djangoenv
fix(seo): https still broken on -test — key site_scheme off DJANGO_ENV not DEBUG (#1236)
2 parents 45095b3 + e2ca8b2 commit 5faf178

3 files changed

Lines changed: 46 additions & 33 deletions

File tree

website/context_processors.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from .models import News
1111
from django.conf import settings
12+
from website.utils.metadata import site_scheme as metadata_site_scheme
1213

1314
def recent_news(request):
1415
""" context processors returning recent news """
@@ -19,28 +20,16 @@ def recent_news(request):
1920

2021
def site_scheme(request):
2122
"""
22-
Expose the canonical URL scheme (``http`` / ``https``) to every template.
23-
24-
The site runs behind UW CSE's Apache TLS-terminating proxy, which talks to
25-
the Django container over plain HTTP. Because ``SECURE_PROXY_SSL_HEADER`` is
26-
not (yet) configured, ``request.scheme`` reports ``http`` in production/test
27-
even though visitors arrive over HTTPS. Building absolute URLs (canonical,
28-
Open Graph ``og:url``/``og:image``, Twitter Card images) from
29-
``request.scheme`` therefore advertises ``http://`` links to crawlers and
30-
social scrapers — the root cause of issue #1236.
31-
32-
This processor pins the scheme to ``https`` whenever the site is not in
33-
DEBUG (i.e. on the test/prod servers), while leaving local dev on whatever
34-
``request.scheme`` reports (``http`` over localhost). Templates should build
35-
absolute URLs as ``{{ site_scheme }}://{{ request.get_host }}{{ path }}``.
36-
37-
NOTE: This is the in-repo workaround. The cleaner long-term fix is for IT to
38-
set ``SECURE_PROXY_SSL_HEADER`` on the proxy (tracked in #1329); once that
39-
lands, ``request.scheme`` will be correct and this can fall back to it.
23+
Expose the canonical URL scheme (``http`` / ``https``) to every template, so
24+
templates can build absolute URLs as
25+
``{{ site_scheme }}://{{ request.get_host }}{{ path }}`` that aren't ``http://``
26+
behind UW CSE's TLS-terminating proxy (issue #1236).
27+
28+
Delegates to :func:`website.utils.metadata.site_scheme` (the single source of
29+
truth, keyed on ``DJANGO_ENV``) so the scheme used by view-built JSON-LD URLs
30+
and template-built canonical/OG URLs can't drift.
4031
"""
41-
return {
42-
'site_scheme': request.scheme if settings.DEBUG else 'https',
43-
}
32+
return {'site_scheme': metadata_site_scheme(request)}
4433

4534
def admin_version_info(request):
4635
"""

website/tests/test_page_metadata.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ def _position(person, title=None):
4646
)
4747

4848

49-
# On the servers DEBUG is False, so site_scheme pins https — assert against that
50-
# (the test client's host is "testserver", auto-added to ALLOWED_HOSTS).
51-
@override_settings(DEBUG=False)
49+
# On the servers (DJANGO_ENV TEST/PROD) site_scheme pins https — assert against
50+
# that (the test client's host is "testserver", auto-added to ALLOWED_HOSTS).
51+
# NB: DJANGO_ENV, not DEBUG — the test server runs DEBUG=True behind the proxy
52+
# (see PageMetadataSchemeTests for the regression that motivated this).
53+
@override_settings(DJANGO_ENV='PROD')
5254
class PageMetadataHttpsTests(DatabaseTestCase):
5355

5456
def test_home_has_core_metadata(self):
@@ -204,10 +206,25 @@ def test_jsonld_escapes_script_breakout(self):
204206

205207

206208
class PageMetadataSchemeTests(DatabaseTestCase):
209+
"""site_scheme keys off DJANGO_ENV, not DEBUG. The test server runs DEBUG=True
210+
behind the same TLS proxy as prod, so a DEBUG-based check would emit http://
211+
there (regression for the #1236 follow-up fix)."""
207212

208-
@override_settings(DEBUG=True)
213+
@override_settings(DJANGO_ENV='TEST', DEBUG=True)
214+
def test_test_server_uses_https_even_with_debug_true(self):
215+
"""The crux: DJANGO_ENV=TEST + DEBUG=True must still emit https."""
216+
resp = self.client.get(reverse("website:index"))
217+
self.assertContains(resp, '<link rel="canonical" href="https://testserver/">')
218+
self.assertContains(resp, '<meta property="og:url" content="https://testserver/">')
219+
220+
@override_settings(DJANGO_ENV='PROD', DEBUG=False)
221+
def test_prod_uses_https(self):
222+
resp = self.client.get(reverse("website:index"))
223+
self.assertContains(resp, '<meta property="og:url" content="https://testserver/">')
224+
225+
@override_settings(DJANGO_ENV='DEBUG', DEBUG=True)
209226
def test_local_dev_uses_request_scheme(self):
210-
"""In DEBUG (local dev over http) the absolute URLs follow request.scheme."""
227+
"""Local dev (DJANGO_ENV=DEBUG/unset over http) follows request.scheme."""
211228
resp = self.client.get(reverse("website:index"))
212229
self.assertContains(resp, '<link rel="canonical" href="http://testserver/">')
213230
self.assertContains(resp, '<meta property="og:url" content="http://testserver/">')

website/utils/metadata.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,21 @@ def meta_description(html, max_chars=META_DESCRIPTION_MAX_CHARS):
4545

4646
def site_scheme(request):
4747
"""
48-
The canonical scheme for absolute URLs built in views (https on the servers,
49-
request.scheme in local dev). Mirrors the ``site_scheme`` context processor
50-
(website/context_processors.py) so view-built JSON-LD URLs match the
51-
template-built canonical/OG URLs. See #1236 (and #1329 for the IT-side
52-
SECURE_PROXY_SSL_HEADER follow-up that would let this fall back to
53-
request.scheme).
48+
The canonical scheme for absolute URLs (https on the test/prod servers,
49+
``request.scheme`` in local dev). Single source of truth — the ``site_scheme``
50+
context processor delegates here, so view-built JSON-LD URLs and template-built
51+
canonical/OG URLs always agree.
52+
53+
We key off ``DJANGO_ENV``, NOT ``DEBUG``: the **test** server runs with
54+
``DEBUG=True`` (config-test.ini) yet sits behind the same TLS-terminating Apache
55+
proxy as prod, so a DEBUG-based check emits ``http://`` on test — the exact #1236
56+
bug. ``DJANGO_ENV`` is ``'TEST'``/``'PROD'`` on the servers (set by
57+
rebuildanddeploy.sh) and ``'DEBUG'``/unset locally, which is the signal we want.
58+
59+
NOTE: in-repo workaround. #1329 (IT enabling SECURE_PROXY_SSL_HEADER) would make
60+
request.scheme correct everywhere and let this fall back to it.
5461
"""
55-
return request.scheme if settings.DEBUG else 'https'
62+
return 'https' if settings.DJANGO_ENV in ('PROD', 'TEST') else request.scheme
5663

5764

5865
def absolute_url(request, path):

0 commit comments

Comments
 (0)