Commit 1183f6ce by Toby Lawrence

Add the ability to exclude files from URL canonicalization.

To be able to more easily deal with same-origin issues, due to some course assets being loaded in an iframe, we're adding the ability to specify file extensions that should be excluded from URL canonicalization.  The default value is simply 'html', which means we won't rewrite asset links that point to files ending in .html.  Thus, they'll be loaded from the same origin as the parent page, and voila, no SOP issues.
parent f43e1961
...@@ -5,7 +5,7 @@ from django.contrib.staticfiles.storage import staticfiles_storage ...@@ -5,7 +5,7 @@ from django.contrib.staticfiles.storage import staticfiles_storage
from django.contrib.staticfiles import finders from django.contrib.staticfiles import finders
from django.conf import settings from django.conf import settings
from static_replace.models import AssetBaseUrlConfig from static_replace.models import AssetBaseUrlConfig, AssetExcludedExtensionsConfig
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import StaticContent
...@@ -182,7 +182,8 @@ def replace_static_urls(text, data_directory=None, course_id=None, static_asset_ ...@@ -182,7 +182,8 @@ def replace_static_urls(text, data_directory=None, course_id=None, static_asset_
# if not, then assume it's courseware specific content and then look in the # if not, then assume it's courseware specific content and then look in the
# Mongo-backed database # Mongo-backed database
base_url = AssetBaseUrlConfig.get_base_url() base_url = AssetBaseUrlConfig.get_base_url()
url = StaticContent.get_canonicalized_asset_path(course_id, rest, base_url) excluded_exts = AssetExcludedExtensionsConfig.get_excluded_extensions()
url = StaticContent.get_canonicalized_asset_path(course_id, rest, base_url, excluded_exts)
if AssetLocator.CANONICAL_NAMESPACE in url: if AssetLocator.CANONICAL_NAMESPACE in url:
url = url.replace('block@', 'block/', 1) url = url.replace('block@', 'block/', 1)
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('static_replace', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='AssetExcludedExtensionsConfig',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
('excluded_extensions', models.TextField(default=b'html', help_text=b'The file extensions to exclude from canonicalization. No leading period required. Values should be space separated i.e. "html svg css"')),
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
],
),
]
...@@ -27,3 +27,27 @@ class AssetBaseUrlConfig(ConfigurationModel): ...@@ -27,3 +27,27 @@ class AssetBaseUrlConfig(ConfigurationModel):
def __unicode__(self): def __unicode__(self):
return unicode(repr(self)) return unicode(repr(self))
class AssetExcludedExtensionsConfig(ConfigurationModel):
"""Configuration for the the excluded file extensions when canonicalizing static asset paths."""
class Meta(object):
app_label = 'static_replace'
excluded_extensions = TextField(
default='html',
help_text='The file extensions to exclude from canonicalization. No leading period required. ' +
'Values should be space separated i.e. "html svg css"'
)
@classmethod
def get_excluded_extensions(cls):
"""Gets the excluded file extensions when canonicalizing static asset paths"""
return cls.current().excluded_extensions.split()
def __repr__(self):
return '<AssetExcludedExtensionsConfig(extensions={})>'.format(self.get_excluded_extensions().split())
def __unicode__(self):
return unicode(repr(self))
...@@ -98,11 +98,13 @@ def test_storage_url_not_exists(mock_storage): ...@@ -98,11 +98,13 @@ def test_storage_url_not_exists(mock_storage):
@patch('static_replace.StaticContent', autospec=True) @patch('static_replace.StaticContent', autospec=True)
@patch('static_replace.modulestore', autospec=True) @patch('static_replace.modulestore', autospec=True)
@patch('static_replace.AssetBaseUrlConfig.get_base_url') @patch('static_replace.AssetBaseUrlConfig.get_base_url')
def test_mongo_filestore(mock_get_base_url, mock_modulestore, mock_static_content): @patch('static_replace.AssetExcludedExtensionsConfig.get_excluded_extensions')
def test_mongo_filestore(mock_get_excluded_extensions, mock_get_base_url, mock_modulestore, mock_static_content):
mock_modulestore.return_value = Mock(MongoModuleStore) mock_modulestore.return_value = Mock(MongoModuleStore)
mock_static_content.get_canonicalized_asset_path.return_value = "c4x://mock_url" mock_static_content.get_canonicalized_asset_path.return_value = "c4x://mock_url"
mock_get_base_url.return_value = u'' mock_get_base_url.return_value = u''
mock_get_excluded_extensions.return_value = ['foobar']
# No namespace => no change to path # No namespace => no change to path
assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY))
...@@ -113,7 +115,7 @@ def test_mongo_filestore(mock_get_base_url, mock_modulestore, mock_static_conten ...@@ -113,7 +115,7 @@ def test_mongo_filestore(mock_get_base_url, mock_modulestore, mock_static_conten
replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY, course_id=COURSE_KEY) replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY, course_id=COURSE_KEY)
) )
mock_static_content.get_canonicalized_asset_path.assert_called_once_with(COURSE_KEY, 'file.png', u'') mock_static_content.get_canonicalized_asset_path.assert_called_once_with(COURSE_KEY, 'file.png', u'', ['foobar'])
@patch('static_replace.settings', autospec=True) @patch('static_replace.settings', autospec=True)
...@@ -217,6 +219,13 @@ class CanonicalContentTest(SharedModuleStoreTestCase): ...@@ -217,6 +219,13 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
# Create an unlocked image with funky characters in the name. # Create an unlocked image with funky characters in the name.
cls.create_image(prefix, (1, 1), 'black', 'weird {}_unlock.png') cls.create_image(prefix, (1, 1), 'black', 'weird {}_unlock.png')
cls.create_image(prefix, (1, 1), 'black', 'special/weird {}_unlock.png')
# Create an HTML file to test extension exclusion, and create a control file.
cls.create_arbitrary_content(prefix, '{}_not_excluded.htm')
cls.create_arbitrary_content(prefix, '{}_excluded.html')
cls.create_arbitrary_content(prefix, 'special/{}_not_excluded.htm')
cls.create_arbitrary_content(prefix, 'special/{}_excluded.html')
@classmethod @classmethod
def create_image(cls, prefix, dimensions, color, name, locked=False): def create_image(cls, prefix, dimensions, color, name, locked=False):
...@@ -244,83 +253,195 @@ class CanonicalContentTest(SharedModuleStoreTestCase): ...@@ -244,83 +253,195 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
return new_content return new_content
@classmethod
def create_arbitrary_content(cls, prefix, name, locked=False):
"""
Creates an arbitrary piece of content with a fixed body, for when content doesn't matter.
Args:
prefix: the prefix to use e.g. split vs mongo
name: the name of the content; can be a format string
locked: whether or not the asset should be locked
Returns:
StaticContent: the StaticContent object for the created content
"""
new_buf = StringIO('testingggggggggggg')
new_name = name.format(prefix)
new_key = StaticContent.compute_location(cls.courses[prefix].id, new_name)
new_content = StaticContent(new_key, new_name, 'application/octet-stream', new_buf.getvalue(), locked=locked)
contentstore().save(new_content)
return new_content
@ddt.data( @ddt.data(
# No leading slash. # No leading slash.
(u'', u'{prefix}_unlock.png', u'/{asset_key}@{prefix}_unlock.png', 1), (u'', u'{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
(u'', u'{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'', u'weird {prefix}_unlock.png', u'/{asset_key}@weird_{prefix}_unlock.png', 1), (u'', u'weird {prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'{prefix}_unlock.png', u'//dev/{asset_key}@{prefix}_unlock.png', 1), (u'', u'{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'dev', u'{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'{prfx}_not_excluded.htm', u'/{asset}@{prfx}_not_excluded.htm', 1),
(u'dev', u'weird {prefix}_unlock.png', u'//dev/{asset_key}@weird_{prefix}_unlock.png', 1), (u'dev', u'{prfx}_unlock.png', u'//dev/{asset}@{prfx}_unlock.png', 1),
(u'dev', u'{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'dev', u'weird {prfx}_unlock.png', u'//dev/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'dev', u'{prfx}_not_excluded.htm', u'//dev/{asset}@{prfx}_not_excluded.htm', 1),
# No leading slash with subdirectory. This ensures we properly substitute slashes. # No leading slash with subdirectory. This ensures we properly substitute slashes.
(u'', u'special/{prefix}_unlock.png', u'/{asset_key}@special_{prefix}_unlock.png', 1), (u'', u'special/{prfx}_unlock.png', u'/{asset}@special_{prfx}_unlock.png', 1),
(u'', u'special/{prefix}_lock.png', u'/{asset_key}@special_{prefix}_lock.png', 1), (u'', u'special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
(u'dev', u'special/{prefix}_unlock.png', u'//dev/{asset_key}@special_{prefix}_unlock.png', 1), (u'', u'special/weird {prfx}_unlock.png', u'/{asset}@special_weird_{prfx}_unlock.png', 1),
(u'dev', u'special/{prefix}_lock.png', u'/{asset_key}@special_{prefix}_lock.png', 1), (u'', u'special/{prfx}_excluded.html', u'/{asset}@special_{prfx}_excluded.html', 1),
(u'', u'special/{prfx}_not_excluded.htm', u'/{asset}@special_{prfx}_not_excluded.htm', 1),
(u'dev', u'special/{prfx}_unlock.png', u'//dev/{asset}@special_{prfx}_unlock.png', 1),
(u'dev', u'special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
(u'dev', u'special/weird {prfx}_unlock.png', u'//dev/{asset}@special_weird_{prfx}_unlock.png', 1),
(u'dev', u'special/{prfx}_excluded.html', u'/{asset}@special_{prfx}_excluded.html', 1),
(u'dev', u'special/{prfx}_not_excluded.htm', u'//dev/{asset}@special_{prfx}_not_excluded.htm', 1),
# Leading slash. # Leading slash.
(u'', u'/{prefix}_unlock.png', u'/{asset_key}@{prefix}_unlock.png', 1), (u'', u'/{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
(u'', u'/{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'/{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'dev', u'/{prefix}_unlock.png', u'//dev/{asset_key}@{prefix}_unlock.png', 1), (u'', u'/weird {prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'/{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'/{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'', u'/{prfx}_not_excluded.htm', u'/{asset}@{prfx}_not_excluded.htm', 1),
(u'dev', u'/{prfx}_unlock.png', u'//dev/{asset}@{prfx}_unlock.png', 1),
(u'dev', u'/{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'dev', u'/weird {prfx}_unlock.png', u'//dev/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'/{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'dev', u'/{prfx}_not_excluded.htm', u'//dev/{asset}@{prfx}_not_excluded.htm', 1),
# Leading slash with subdirectory. This ensures we properly substitute slashes. # Leading slash with subdirectory. This ensures we properly substitute slashes.
(u'', u'/special/{prefix}_unlock.png', u'/{asset_key}@special_{prefix}_unlock.png', 1), (u'', u'/special/{prfx}_unlock.png', u'/{asset}@special_{prfx}_unlock.png', 1),
(u'', u'/special/{prefix}_lock.png', u'/{asset_key}@special_{prefix}_lock.png', 1), (u'', u'/special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
(u'dev', u'/special/{prefix}_unlock.png', u'//dev/{asset_key}@special_{prefix}_unlock.png', 1), (u'', u'/special/weird {prfx}_unlock.png', u'/{asset}@special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/special/{prefix}_lock.png', u'/{asset_key}@special_{prefix}_lock.png', 1), (u'', u'/special/{prfx}_excluded.html', u'/{asset}@special_{prfx}_excluded.html', 1),
(u'', u'/special/{prfx}_not_excluded.htm', u'/{asset}@special_{prfx}_not_excluded.htm', 1),
(u'dev', u'/special/{prfx}_unlock.png', u'//dev/{asset}@special_{prfx}_unlock.png', 1),
(u'dev', u'/special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
(u'dev', u'/special/weird {prfx}_unlock.png', u'//dev/{asset}@special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/special/{prfx}_excluded.html', u'/{asset}@special_{prfx}_excluded.html', 1),
(u'dev', u'/special/{prfx}_not_excluded.htm', u'//dev/{asset}@special_{prfx}_not_excluded.htm', 1),
# Static path. # Static path.
(u'', u'/static/{prefix}_unlock.png', u'/{asset_key}@{prefix}_unlock.png', 1), (u'', u'/static/{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
(u'', u'/static/{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'/static/{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'', u'/static/weird {prefix}_unlock.png', u'/{asset_key}@weird_{prefix}_unlock.png', 1), (u'', u'/static/weird {prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/{prefix}_unlock.png', u'//dev/{asset_key}@{prefix}_unlock.png', 1), (u'', u'/static/{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'dev', u'/static/{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'/static/{prfx}_not_excluded.htm', u'/{asset}@{prfx}_not_excluded.htm', 1),
(u'dev', u'/static/weird {prefix}_unlock.png', u'//dev/{asset_key}@weird_{prefix}_unlock.png', 1), (u'dev', u'/static/{prfx}_unlock.png', u'//dev/{asset}@{prfx}_unlock.png', 1),
(u'dev', u'/static/{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'dev', u'/static/weird {prfx}_unlock.png', u'//dev/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'dev', u'/static/{prfx}_not_excluded.htm', u'//dev/{asset}@{prfx}_not_excluded.htm', 1),
# Static path with subdirectory. This ensures we properly substitute slashes. # Static path with subdirectory. This ensures we properly substitute slashes.
(u'', u'/static/special/{prefix}_unlock.png', u'/{asset_key}@special_{prefix}_unlock.png', 1), (u'', u'/static/special/{prfx}_unlock.png', u'/{asset}@special_{prfx}_unlock.png', 1),
(u'', u'/static/special/{prefix}_lock.png', u'/{asset_key}@special_{prefix}_lock.png', 1), (u'', u'/static/special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
(u'dev', u'/static/special/{prefix}_unlock.png', u'//dev/{asset_key}@special_{prefix}_unlock.png', 1), (u'', u'/static/special/weird {prfx}_unlock.png', u'/{asset}@special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/special/{prefix}_lock.png', u'/{asset_key}@special_{prefix}_lock.png', 1), (u'', u'/static/special/{prfx}_excluded.html', u'/{asset}@special_{prfx}_excluded.html', 1),
(u'', u'/static/special/{prfx}_not_excluded.htm', u'/{asset}@special_{prfx}_not_excluded.htm', 1),
(u'dev', u'/static/special/{prfx}_unlock.png', u'//dev/{asset}@special_{prfx}_unlock.png', 1),
(u'dev', u'/static/special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
(u'dev', u'/static/special/weird {prfx}_unlock.png', u'//dev/{asset}@special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/special/{prfx}_excluded.html', u'/{asset}@special_{prfx}_excluded.html', 1),
(u'dev', u'/static/special/{prfx}_not_excluded.htm', u'//dev/{asset}@special_{prfx}_not_excluded.htm', 1),
# Static path with query parameter. # Static path with query parameter.
( (
u'', u'',
u'/static/{prefix}_unlock.png?foo=/static/{prefix}_lock.png', u'/static/{prfx}_unlock.png?foo=/static/{prfx}_lock.png',
u'/{asset_key}@{prefix}_unlock.png?foo={encoded_asset_key}{prefix}_lock.png', u'/{asset}@{prfx}_unlock.png?foo={encoded_asset}{prfx}_lock.png',
2
),
(
u'',
u'/static/{prfx}_lock.png?foo=/static/{prfx}_unlock.png',
u'/{asset}@{prfx}_lock.png?foo={encoded_asset}{prfx}_unlock.png',
2 2
), ),
( (
u'', u'',
u'/static/{prefix}_lock.png?foo=/static/{prefix}_unlock.png', u'/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html',
u'/{asset_key}@{prefix}_lock.png?foo={encoded_asset_key}{prefix}_unlock.png', u'/{asset}@{prfx}_excluded.html?foo={encoded_asset}{prfx}_excluded.html',
2
),
(
u'',
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm',
u'/{asset}@{prfx}_excluded.html?foo={encoded_asset}{prfx}_not_excluded.htm',
2
),
(
u'',
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html',
u'/{asset}@{prfx}_not_excluded.htm?foo={encoded_asset}{prfx}_excluded.html',
2
),
(
u'',
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_not_excluded.htm',
u'/{asset}@{prfx}_not_excluded.htm?foo={encoded_asset}{prfx}_not_excluded.htm',
2
),
(
u'dev',
u'/static/{prfx}_unlock.png?foo=/static/{prfx}_lock.png',
u'//dev/{asset}@{prfx}_unlock.png?foo={encoded_asset}{prfx}_lock.png',
2
),
(
u'dev',
u'/static/{prfx}_lock.png?foo=/static/{prfx}_unlock.png',
u'/{asset}@{prfx}_lock.png?foo={encoded_base_url}{encoded_asset}{prfx}_unlock.png',
2 2
), ),
( (
u'dev', u'dev',
u'/static/{prefix}_unlock.png?foo=/static/{prefix}_lock.png', u'/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html',
u'//dev/{asset_key}@{prefix}_unlock.png?foo={encoded_asset_key}{prefix}_lock.png', u'/{asset}@{prfx}_excluded.html?foo={encoded_asset}{prfx}_excluded.html',
2 2
), ),
( (
u'dev', u'dev',
u'/static/{prefix}_lock.png?foo=/static/{prefix}_unlock.png', u'/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm',
u'/{asset_key}@{prefix}_lock.png?foo={encoded_base_url}{encoded_asset_key}{prefix}_unlock.png', u'/{asset}@{prfx}_excluded.html?foo={encoded_base_url}{encoded_asset}{prfx}_not_excluded.htm',
2
),
(
u'dev',
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html',
u'//dev/{asset}@{prfx}_not_excluded.htm?foo={encoded_asset}{prfx}_excluded.html',
2
),
(
u'dev',
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_not_excluded.htm',
u'//dev/{asset}@{prfx}_not_excluded.htm?foo={encoded_base_url}{encoded_asset}{prfx}_not_excluded.htm',
2 2
), ),
# Already asset key. # Already asset key.
(u'', u'/{asset_key}@{prefix}_unlock.png', u'/{asset_key}@{prefix}_unlock.png', 1), (u'', u'/{asset}@{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
(u'', u'/{asset_key}@{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'/{asset}@{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'dev', u'/{asset_key}@{prefix}_unlock.png', u'//dev/{asset_key}@{prefix}_unlock.png', 1), (u'', u'/{asset}@weird_{prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'/{asset_key}@{prefix}_lock.png', u'/{asset_key}@{prefix}_lock.png', 1), (u'', u'/{asset}@{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'', u'/{asset}@{prfx}_not_excluded.htm', u'/{asset}@{prfx}_not_excluded.htm', 1),
(u'dev', u'/{asset}@{prfx}_unlock.png', u'//dev/{asset}@{prfx}_unlock.png', 1),
(u'dev', u'/{asset}@{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
(u'dev', u'/{asset}@weird_{prfx}_unlock.png', u'//dev/{asset}@weird_{prfx}_unlock.png', 1),
(u'dev', u'/{asset}@{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
(u'dev', u'/{asset}@{prfx}_not_excluded.htm', u'//dev/{asset}@{prfx}_not_excluded.htm', 1),
# Old, c4x-style path. # Old, c4x-style path.
(u'', u'/{c4x}/{prefix}_unlock.png', u'/{c4x}/{prefix}_unlock.png', 1), (u'', u'/{c4x}/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
(u'', u'/{c4x}/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/{c4x}/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'', u'/{c4x}/weird_{prefix}_lock.png', u'/{c4x}/weird_{prefix}_lock.png', 1), (u'', u'/{c4x}/weird_{prfx}_lock.png', u'/{c4x}/weird_{prfx}_lock.png', 1),
(u'dev', u'/{c4x}/{prefix}_unlock.png', u'/{c4x}/{prefix}_unlock.png', 1), (u'', u'/{c4x}/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/{c4x}/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/{c4x}/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
(u'dev', u'/{c4x}/weird_{prefix}_unlock.png', u'/{c4x}/weird_{prefix}_unlock.png', 1), (u'dev', u'/{c4x}/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
(u'dev', u'/{c4x}/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'dev', u'/{c4x}/weird_{prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'/{c4x}/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/{c4x}/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
# Thumbnails. # Thumbnails.
(u'', u'/{th_key}@{prefix}_unlock-{th_ext}', u'/{th_key}@{prefix}_unlock-{th_ext}', 1), (u'', u'/{th_key}@{prfx}_unlock-{th_ext}', u'/{th_key}@{prfx}_unlock-{th_ext}', 1),
(u'', u'/{th_key}@{prefix}_lock-{th_ext}', u'/{th_key}@{prefix}_lock-{th_ext}', 1), (u'', u'/{th_key}@{prfx}_lock-{th_ext}', u'/{th_key}@{prfx}_lock-{th_ext}', 1),
(u'dev', u'/{th_key}@{prefix}_unlock-{th_ext}', u'//dev/{th_key}@{prefix}_unlock-{th_ext}', 1), (u'dev', u'/{th_key}@{prfx}_unlock-{th_ext}', u'//dev/{th_key}@{prfx}_unlock-{th_ext}', 1),
(u'dev', u'/{th_key}@{prefix}_lock-{th_ext}', u'//dev/{th_key}@{prefix}_lock-{th_ext}', 1), (u'dev', u'/{th_key}@{prfx}_lock-{th_ext}', u'//dev/{th_key}@{prfx}_lock-{th_ext}', 1),
) )
@ddt.unpack @ddt.unpack
def test_canonical_asset_path_with_new_style_assets(self, base_url, start, expected, mongo_calls): def test_canonical_asset_path_with_new_style_assets(self, base_url, start, expected, mongo_calls):
...@@ -333,95 +454,179 @@ class CanonicalContentTest(SharedModuleStoreTestCase): ...@@ -333,95 +454,179 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
th_ext = 'png-16x16.jpg' th_ext = 'png-16x16.jpg'
start = start.format( start = start.format(
prefix=prefix, prfx=prefix,
c4x=c4x, c4x=c4x,
asset_key=asset_key, asset=asset_key,
encoded_base_url=encoded_base_url, encoded_base_url=encoded_base_url,
encoded_asset_key=encoded_asset_key, encoded_asset=encoded_asset_key,
th_key=th_key, th_key=th_key,
th_ext=th_ext th_ext=th_ext
) )
expected = expected.format( expected = expected.format(
prefix=prefix, prfx=prefix,
c4x=c4x, c4x=c4x,
asset_key=asset_key, asset=asset_key,
encoded_base_url=encoded_base_url, encoded_base_url=encoded_base_url,
encoded_asset_key=encoded_asset_key, encoded_asset=encoded_asset_key,
th_key=th_key, th_key=th_key,
th_ext=th_ext th_ext=th_ext
) )
with check_mongo_calls(mongo_calls): with check_mongo_calls(mongo_calls):
asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url) asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url, ['html'])
self.assertEqual(asset_path, expected) self.assertEqual(asset_path, expected)
@ddt.data( @ddt.data(
# No leading slash. # No leading slash.
(u'', u'{prefix}_unlock.png', u'/{c4x}/{prefix}_unlock.png', 1), (u'', u'{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
(u'', u'{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'', u'weird {prefix}_unlock.png', u'/{c4x}/weird_{prefix}_unlock.png', 1), (u'', u'weird {prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'{prefix}_unlock.png', u'//dev/{c4x}/{prefix}_unlock.png', 1), (u'', u'{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
(u'dev', u'weird {prefix}_unlock.png', u'//dev/{c4x}/weird_{prefix}_unlock.png', 1), (u'dev', u'{prfx}_unlock.png', u'//dev/{c4x}/{prfx}_unlock.png', 1),
(u'dev', u'{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'dev', u'weird {prfx}_unlock.png', u'//dev/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'{prfx}_not_excluded.htm', u'//dev/{c4x}/{prfx}_not_excluded.htm', 1),
# No leading slash with subdirectory. This ensures we probably substitute slashes. # No leading slash with subdirectory. This ensures we probably substitute slashes.
(u'', u'special/{prefix}_unlock.png', u'/{c4x}/special_{prefix}_unlock.png', 1), (u'', u'special/{prfx}_unlock.png', u'/{c4x}/special_{prfx}_unlock.png', 1),
(u'', u'special/{prefix}_lock.png', u'/{c4x}/special_{prefix}_lock.png', 1), (u'', u'special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
(u'dev', u'special/{prefix}_unlock.png', u'//dev/{c4x}/special_{prefix}_unlock.png', 1), (u'', u'special/weird {prfx}_unlock.png', u'/{c4x}/special_weird_{prfx}_unlock.png', 1),
(u'dev', u'special/{prefix}_lock.png', u'/{c4x}/special_{prefix}_lock.png', 1), (u'', u'special/{prfx}_excluded.html', u'/{c4x}/special_{prfx}_excluded.html', 1),
(u'', u'special/{prfx}_not_excluded.htm', u'/{c4x}/special_{prfx}_not_excluded.htm', 1),
(u'dev', u'special/{prfx}_unlock.png', u'//dev/{c4x}/special_{prfx}_unlock.png', 1),
(u'dev', u'special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
(u'dev', u'special/weird {prfx}_unlock.png', u'//dev/{c4x}/special_weird_{prfx}_unlock.png', 1),
(u'dev', u'special/{prfx}_excluded.html', u'/{c4x}/special_{prfx}_excluded.html', 1),
(u'dev', u'special/{prfx}_not_excluded.htm', u'//dev/{c4x}/special_{prfx}_not_excluded.htm', 1),
# Leading slash. # Leading slash.
(u'', u'/{prefix}_unlock.png', u'/{c4x}/{prefix}_unlock.png', 1), (u'', u'/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
(u'', u'/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'dev', u'/{prefix}_unlock.png', u'//dev/{c4x}/{prefix}_unlock.png', 1), (u'', u'/weird {prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'', u'/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
(u'dev', u'/{prfx}_unlock.png', u'//dev/{c4x}/{prfx}_unlock.png', 1),
(u'dev', u'/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'dev', u'/weird {prfx}_unlock.png', u'//dev/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/{prfx}_not_excluded.htm', u'//dev/{c4x}/{prfx}_not_excluded.htm', 1),
# Leading slash with subdirectory. This ensures we properly substitute slashes. # Leading slash with subdirectory. This ensures we properly substitute slashes.
(u'', u'/special/{prefix}_unlock.png', u'/{c4x}/special_{prefix}_unlock.png', 1), (u'', u'/special/{prfx}_unlock.png', u'/{c4x}/special_{prfx}_unlock.png', 1),
(u'', u'/special/{prefix}_lock.png', u'/{c4x}/special_{prefix}_lock.png', 1), (u'', u'/special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
(u'dev', u'/special/{prefix}_unlock.png', u'//dev/{c4x}/special_{prefix}_unlock.png', 1), (u'', u'/special/weird {prfx}_unlock.png', u'/{c4x}/special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/special/{prefix}_lock.png', u'/{c4x}/special_{prefix}_lock.png', 1), (u'', u'/special/{prfx}_excluded.html', u'/{c4x}/special_{prfx}_excluded.html', 1),
(u'', u'/special/{prfx}_not_excluded.htm', u'/{c4x}/special_{prfx}_not_excluded.htm', 1),
(u'dev', u'/special/{prfx}_unlock.png', u'//dev/{c4x}/special_{prfx}_unlock.png', 1),
(u'dev', u'/special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
(u'dev', u'/special/weird {prfx}_unlock.png', u'//dev/{c4x}/special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/special/{prfx}_excluded.html', u'/{c4x}/special_{prfx}_excluded.html', 1),
(u'dev', u'/special/{prfx}_not_excluded.htm', u'//dev/{c4x}/special_{prfx}_not_excluded.htm', 1),
# Static path. # Static path.
(u'', u'/static/{prefix}_unlock.png', u'/{c4x}/{prefix}_unlock.png', 1), (u'', u'/static/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
(u'', u'/static/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/static/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'', u'/static/weird {prefix}_unlock.png', u'/{c4x}/weird_{prefix}_unlock.png', 1), (u'', u'/static/weird {prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/{prefix}_unlock.png', u'//dev/{c4x}/{prefix}_unlock.png', 1), (u'', u'/static/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/static/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/static/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
(u'dev', u'/static/weird {prefix}_unlock.png', u'//dev/{c4x}/weird_{prefix}_unlock.png', 1), (u'dev', u'/static/{prfx}_unlock.png', u'//dev/{c4x}/{prfx}_unlock.png', 1),
(u'dev', u'/static/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'dev', u'/static/weird {prfx}_unlock.png', u'//dev/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/static/{prfx}_not_excluded.htm', u'//dev/{c4x}/{prfx}_not_excluded.htm', 1),
# Static path with subdirectory. This ensures we properly substitute slashes. # Static path with subdirectory. This ensures we properly substitute slashes.
(u'', u'/static/special/{prefix}_unlock.png', u'/{c4x}/special_{prefix}_unlock.png', 1), (u'', u'/static/special/{prfx}_unlock.png', u'/{c4x}/special_{prfx}_unlock.png', 1),
(u'', u'/static/special/{prefix}_lock.png', u'/{c4x}/special_{prefix}_lock.png', 1), (u'', u'/static/special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
(u'dev', u'/static/special/{prefix}_unlock.png', u'//dev/{c4x}/special_{prefix}_unlock.png', 1), (u'', u'/static/special/weird {prfx}_unlock.png', u'/{c4x}/special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/special/{prefix}_lock.png', u'/{c4x}/special_{prefix}_lock.png', 1), (u'', u'/static/special/{prfx}_excluded.html', u'/{c4x}/special_{prfx}_excluded.html', 1),
(u'', u'/static/special/{prfx}_not_excluded.htm', u'/{c4x}/special_{prfx}_not_excluded.htm', 1),
(u'dev', u'/static/special/{prfx}_unlock.png', u'//dev/{c4x}/special_{prfx}_unlock.png', 1),
(u'dev', u'/static/special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
(u'dev', u'/static/special/weird {prfx}_unlock.png', u'//dev/{c4x}/special_weird_{prfx}_unlock.png', 1),
(u'dev', u'/static/special/{prfx}_excluded.html', u'/{c4x}/special_{prfx}_excluded.html', 1),
(u'dev', u'/static/special/{prfx}_not_excluded.htm', u'//dev/{c4x}/special_{prfx}_not_excluded.htm', 1),
# Static path with query parameter. # Static path with query parameter.
( (
u'', u'',
u'/static/{prefix}_unlock.png?foo=/static/{prefix}_lock.png', u'/static/{prfx}_unlock.png?foo=/static/{prfx}_lock.png',
u'/{c4x}/{prefix}_unlock.png?foo={encoded_c4x}{prefix}_lock.png', u'/{c4x}/{prfx}_unlock.png?foo={encoded_c4x}{prfx}_lock.png',
2
),
(
u'',
u'/static/{prfx}_lock.png?foo=/static/{prfx}_unlock.png',
u'/{c4x}/{prfx}_lock.png?foo={encoded_c4x}{prfx}_unlock.png',
2
),
(
u'',
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html',
u'/{c4x}/{prfx}_excluded.html?foo={encoded_c4x}{prfx}_excluded.html',
2
),
(
u'',
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm',
u'/{c4x}/{prfx}_excluded.html?foo={encoded_c4x}{prfx}_not_excluded.htm',
2 2
), ),
( (
u'', u'',
u'/static/{prefix}_lock.png?foo=/static/{prefix}_unlock.png', u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html',
u'/{c4x}/{prefix}_lock.png?foo={encoded_c4x}{prefix}_unlock.png', u'/{c4x}/{prfx}_not_excluded.htm?foo={encoded_c4x}{prfx}_excluded.html',
2
),
(
u'',
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_not_excluded.htm',
u'/{c4x}/{prfx}_not_excluded.htm?foo={encoded_c4x}{prfx}_not_excluded.htm',
2
),
(
u'dev',
u'/static/{prfx}_unlock.png?foo=/static/{prfx}_lock.png',
u'//dev/{c4x}/{prfx}_unlock.png?foo={encoded_c4x}{prfx}_lock.png',
2
),
(
u'dev',
u'/static/{prfx}_lock.png?foo=/static/{prfx}_unlock.png',
u'/{c4x}/{prfx}_lock.png?foo={encoded_base_url}{encoded_c4x}{prfx}_unlock.png',
2
),
(
u'dev',
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html',
u'/{c4x}/{prfx}_excluded.html?foo={encoded_c4x}{prfx}_excluded.html',
2
),
(
u'dev',
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm',
u'/{c4x}/{prfx}_excluded.html?foo={encoded_base_url}{encoded_c4x}{prfx}_not_excluded.htm',
2 2
), ),
( (
u'dev', u'dev',
u'/static/{prefix}_unlock.png?foo=/static/{prefix}_lock.png', u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html',
u'//dev/{c4x}/{prefix}_unlock.png?foo={encoded_c4x}{prefix}_lock.png', u'//dev/{c4x}/{prfx}_not_excluded.htm?foo={encoded_c4x}{prfx}_excluded.html',
2 2
), ),
( (
u'dev', u'dev',
u'/static/{prefix}_lock.png?foo=/static/{prefix}_unlock.png', u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_not_excluded.htm',
u'/{c4x}/{prefix}_lock.png?foo={encoded_base_url}{encoded_c4x}{prefix}_unlock.png', u'//dev/{c4x}/{prfx}_not_excluded.htm?foo={encoded_base_url}{encoded_c4x}{prfx}_not_excluded.htm',
2 2
), ),
# Old, c4x-style path. # Old, c4x-style path.
(u'', u'/{c4x}/{prefix}_unlock.png', u'/{c4x}/{prefix}_unlock.png', 1), (u'', u'/{c4x}/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
(u'', u'/{c4x}/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/{c4x}/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'', u'/{c4x}/weird_{prefix}_unlock.png', u'/{c4x}/weird_{prefix}_unlock.png', 1), (u'', u'/{c4x}/weird_{prfx}_lock.png', u'/{c4x}/weird_{prfx}_lock.png', 1),
(u'dev', u'/{c4x}/{prefix}_unlock.png', u'//dev/{c4x}/{prefix}_unlock.png', 1), (u'', u'/{c4x}/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/{c4x}/{prefix}_lock.png', u'/{c4x}/{prefix}_lock.png', 1), (u'', u'/{c4x}/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
(u'dev', u'/{c4x}/weird_{prefix}_unlock.png', u'//dev/{c4x}/weird_{prefix}_unlock.png', 1), (u'dev', u'/{c4x}/{prfx}_unlock.png', u'//dev/{c4x}/{prfx}_unlock.png', 1),
(u'dev', u'/{c4x}/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
(u'dev', u'/{c4x}/weird_{prfx}_unlock.png', u'//dev/{c4x}/weird_{prfx}_unlock.png', 1),
(u'dev', u'/{c4x}/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
(u'dev', u'/{c4x}/{prfx}_not_excluded.htm', u'//dev/{c4x}/{prfx}_not_excluded.htm', 1),
) )
@ddt.unpack @ddt.unpack
def test_canonical_asset_path_with_c4x_style_assets(self, base_url, start, expected, mongo_calls): def test_canonical_asset_path_with_c4x_style_assets(self, base_url, start, expected, mongo_calls):
...@@ -431,18 +636,18 @@ class CanonicalContentTest(SharedModuleStoreTestCase): ...@@ -431,18 +636,18 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
encoded_base_url = quote_plus('//' + base_url) encoded_base_url = quote_plus('//' + base_url)
start = start.format( start = start.format(
prefix=prefix, prfx=prefix,
encoded_base_url=encoded_base_url, encoded_base_url=encoded_base_url,
c4x=c4x_block, c4x=c4x_block,
encoded_c4x=encoded_c4x_block encoded_c4x=encoded_c4x_block
) )
expected = expected.format( expected = expected.format(
prefix=prefix, prfx=prefix,
encoded_base_url=encoded_base_url, encoded_base_url=encoded_base_url,
c4x=c4x_block, c4x=c4x_block,
encoded_c4x=encoded_c4x_block encoded_c4x=encoded_c4x_block
) )
with check_mongo_calls(mongo_calls): with check_mongo_calls(mongo_calls):
asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url) asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url, ['html'])
self.assertEqual(asset_path, expected) self.assertEqual(asset_path, expected)
...@@ -168,7 +168,7 @@ class StaticContent(object): ...@@ -168,7 +168,7 @@ class StaticContent(object):
return StaticContent.compute_location(course_key, path) return StaticContent.compute_location(course_key, path)
@staticmethod @staticmethod
def get_canonicalized_asset_path(course_key, path, base_url): def get_canonicalized_asset_path(course_key, path, base_url, excluded_exts):
""" """
Returns a fully-qualified path to a piece of static content. Returns a fully-qualified path to a piece of static content.
...@@ -199,17 +199,24 @@ class StaticContent(object): ...@@ -199,17 +199,24 @@ class StaticContent(object):
# If we can't find the item, just treat it as if it's locked. # If we can't find the item, just treat it as if it's locked.
serve_from_cdn = False serve_from_cdn = False
# See if this is an allowed file extension to serve. Some files aren't served through the
# CDN in order to avoid same-origin policy/CORS-related issues.
for excluded_ext in excluded_exts:
if relative_path.lower().endswith(excluded_ext.lower()):
serve_from_cdn = False
break
# Update any query parameter values that have asset paths in them. This is for assets that # Update any query parameter values that have asset paths in them. This is for assets that
# require their own after-the-fact values, like a Flash file that needs the path of a config # require their own after-the-fact values, like a Flash file that needs the path of a config
# file passed to it e.g. /static/visualization.swf?configFile=/static/visualization.xml # file passed to it e.g. /static/visualization.swf?configFile=/static/visualization.xml
query_params = parse_qsl(query_string) query_params = parse_qsl(query_string)
updated_query_params = [] updated_query_params = []
for query_name, query_value in query_params: for query_name, query_val in query_params:
if query_value.startswith("/static/"): if query_val.startswith("/static/"):
new_query_value = StaticContent.get_canonicalized_asset_path(course_key, query_value, base_url) new_val = StaticContent.get_canonicalized_asset_path(course_key, query_val, base_url, excluded_exts)
updated_query_params.append((query_name, new_query_value)) updated_query_params.append((query_name, new_val))
else: else:
updated_query_params.append((query_name, query_value)) updated_query_params.append((query_name, query_val))
serialized_asset_key = StaticContent.serialize_asset_key_with_slash(asset_key) serialized_asset_key = StaticContent.serialize_asset_key_with_slash(asset_key)
base_url = base_url if serve_from_cdn else '' base_url = base_url if serve_from_cdn else ''
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment