Revert "[PERF-325] Add versioned course asset URLs when canonicalizing asset paths."
We're seeing errors in NR from objects read out of the cache lacking the
'StaticContent' object has no attribute 'content_digest'
File "/edx/app/edxapp/edx-platform/common/djangoapps/contentserver/middleware.py",
line 70, in process_request
This reverts commit 849ebc5f22.
This commit is contained in:
@@ -3,11 +3,12 @@ Middleware to serve assets.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import datetime
|
||||
import newrelic.agent
|
||||
from django.http import (
|
||||
HttpResponse, HttpResponseNotModified, HttpResponseForbidden,
|
||||
HttpResponseBadRequest, HttpResponseNotFound, HttpResponsePermanentRedirect)
|
||||
HttpResponseBadRequest, HttpResponseNotFound)
|
||||
from student.models import CourseEnrollment
|
||||
from contentserver.models import CourseAssetCacheTtlConfig, CdnUserAgentsConfig
|
||||
|
||||
@@ -29,54 +30,32 @@ HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
|
||||
|
||||
|
||||
class StaticContentServer(object):
|
||||
"""
|
||||
Serves course assets to end users. Colloquially referred to as "contentserver."
|
||||
"""
|
||||
def is_asset_request(self, request):
|
||||
"""Determines whether the given request is an asset request"""
|
||||
return (
|
||||
request.path.startswith('/' + XASSET_LOCATION_TAG + '/')
|
||||
or
|
||||
request.path.startswith('/' + AssetLocator.CANONICAL_NAMESPACE)
|
||||
or
|
||||
StaticContent.is_versioned_asset_path(request.path)
|
||||
)
|
||||
|
||||
def process_request(self, request):
|
||||
"""Process the given request"""
|
||||
asset_path = request.path
|
||||
|
||||
if self.is_asset_request(request):
|
||||
# Make sure we can convert this request into a location.
|
||||
if AssetLocator.CANONICAL_NAMESPACE in asset_path:
|
||||
asset_path = asset_path.replace('block/', 'block@', 1)
|
||||
|
||||
# If this is a versioned request, pull out the digest and chop off the prefix.
|
||||
requested_digest = None
|
||||
if StaticContent.is_versioned_asset_path(asset_path):
|
||||
requested_digest, asset_path = StaticContent.parse_versioned_asset_path(asset_path)
|
||||
|
||||
# Make sure we have a valid location value for this asset.
|
||||
if AssetLocator.CANONICAL_NAMESPACE in request.path:
|
||||
request.path = request.path.replace('block/', 'block@', 1)
|
||||
try:
|
||||
loc = StaticContent.get_location_from_path(asset_path)
|
||||
loc = StaticContent.get_location_from_path(request.path)
|
||||
except (InvalidLocationError, InvalidKeyError):
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
# Attempt to load the asset to make sure it exists, and grab the asset digest
|
||||
# if we're able to load it.
|
||||
actual_digest = None
|
||||
# Try and load the asset.
|
||||
content = None
|
||||
try:
|
||||
content = self.load_asset_from_location(loc)
|
||||
actual_digest = content.content_digest
|
||||
except (ItemNotFoundError, NotFoundError):
|
||||
return HttpResponseNotFound()
|
||||
|
||||
# If this was a versioned asset, and the digest doesn't match, redirect
|
||||
# them to the actual version.
|
||||
if requested_digest is not None and (actual_digest != requested_digest):
|
||||
actual_asset_path = StaticContent.add_version_to_asset_path(asset_path, actual_digest)
|
||||
return HttpResponsePermanentRedirect(actual_asset_path)
|
||||
|
||||
# Set the basics for this request. Make sure that the course key for this
|
||||
# asset has a run, which old-style courses do not. Otherwise, this will
|
||||
# explode when the key is serialized to be sent to NR.
|
||||
|
||||
@@ -16,13 +16,9 @@ from django.test.utils import override_settings
|
||||
from mock import patch
|
||||
|
||||
from xmodule.contentstore.django import contentstore
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
from xmodule.assetstore.assetmgr import AssetManager
|
||||
from opaque_keys import InvalidKeyError
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
|
||||
from contentserver.middleware import parse_range_header, HTTP_DATE_FORMAT, StaticContentServer
|
||||
from student.models import CourseEnrollment
|
||||
@@ -32,24 +28,9 @@ log = logging.getLogger(__name__)
|
||||
|
||||
TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE)
|
||||
TEST_DATA_CONTENTSTORE['DOC_STORE_CONFIG']['db'] = 'test_xcontent_%s' % uuid4().hex
|
||||
|
||||
TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT
|
||||
|
||||
FAKE_MD5_HASH = 'ffffffffffffffffffffffffffffffff'
|
||||
|
||||
|
||||
def get_versioned_asset_url(asset_path):
|
||||
"""
|
||||
Creates a versioned asset URL.
|
||||
"""
|
||||
try:
|
||||
locator = StaticContent.get_location_from_path(asset_path)
|
||||
content = AssetManager.find(locator, as_stream=True)
|
||||
return StaticContent.add_version_to_asset_path(asset_path, content.content_digest)
|
||||
except (InvalidKeyError, ItemNotFoundError):
|
||||
pass
|
||||
|
||||
return asset_path
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE)
|
||||
@@ -73,15 +54,13 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase):
|
||||
)
|
||||
|
||||
# A locked asset
|
||||
cls.locked_asset = cls.course_key.make_asset_key('asset', 'sample_static.html')
|
||||
cls.locked_asset = cls.course_key.make_asset_key('asset', 'sample_static.txt')
|
||||
cls.url_locked = unicode(cls.locked_asset)
|
||||
cls.url_locked_versioned = get_versioned_asset_url(cls.url_locked)
|
||||
cls.contentstore.set_attr(cls.locked_asset, 'locked', True)
|
||||
|
||||
# An unlocked asset
|
||||
cls.unlocked_asset = cls.course_key.make_asset_key('asset', 'another_static.txt')
|
||||
cls.url_unlocked = unicode(cls.unlocked_asset)
|
||||
cls.url_unlocked_versioned = get_versioned_asset_url(cls.url_unlocked)
|
||||
cls.length_unlocked = cls.contentstore.get_attr(cls.unlocked_asset, 'length')
|
||||
|
||||
def setUp(self):
|
||||
@@ -102,37 +81,6 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase):
|
||||
resp = self.client.get(self.url_unlocked)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_unlocked_versioned_asset(self):
|
||||
"""
|
||||
Test that unlocked assets that are versioned are being served.
|
||||
"""
|
||||
self.client.logout()
|
||||
resp = self.client.get(self.url_unlocked_versioned)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_unlocked_versioned_asset_with_nonexistent_version(self):
|
||||
"""
|
||||
Test that unlocked assets that are versioned, but have a nonexistent version,
|
||||
are sent back as a 301 redirect which tells the caller the correct URL.
|
||||
"""
|
||||
url_unlocked_versioned_old = StaticContent.add_version_to_asset_path(self.url_unlocked, FAKE_MD5_HASH)
|
||||
|
||||
self.client.logout()
|
||||
resp = self.client.get(url_unlocked_versioned_old)
|
||||
self.assertEqual(resp.status_code, 301)
|
||||
self.assertTrue(resp.url.endswith(self.url_unlocked_versioned)) # pylint: disable=no-member
|
||||
|
||||
def test_locked_versioned_asset(self):
|
||||
"""
|
||||
Test that locked assets that are versioned are being served.
|
||||
"""
|
||||
CourseEnrollment.enroll(self.non_staff_usr, self.course_key)
|
||||
self.assertTrue(CourseEnrollment.is_enrolled(self.non_staff_usr, self.course_key))
|
||||
|
||||
self.client.login(username=self.non_staff_usr, password='test')
|
||||
resp = self.client.get(self.url_locked_versioned)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_locked_asset_not_logged_in(self):
|
||||
"""
|
||||
Test that locked assets behave appropriately in case the user is not
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for static_replace"""
|
||||
|
||||
from urllib import quote_plus
|
||||
|
||||
import ddt
|
||||
import re
|
||||
|
||||
from django.utils.http import urlquote, urlencode
|
||||
from urlparse import urlparse, urlunparse, parse_qsl
|
||||
from PIL import Image
|
||||
from cStringIO import StringIO
|
||||
|
||||
from nose.tools import assert_equals, assert_true, assert_false # pylint: disable=no-name-in-module
|
||||
from static_replace import (
|
||||
replace_static_urls,
|
||||
@@ -17,6 +16,7 @@ from static_replace import (
|
||||
make_static_urls_absolute
|
||||
)
|
||||
from mock import patch, Mock
|
||||
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.contentstore.django import contentstore
|
||||
@@ -25,29 +25,12 @@ from xmodule.modulestore.mongo import MongoModuleStore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls
|
||||
from xmodule.modulestore.xml import XMLModuleStore
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from xmodule.exceptions import NotFoundError
|
||||
from xmodule.assetstore.assetmgr import AssetManager
|
||||
|
||||
DATA_DIRECTORY = 'data_dir'
|
||||
COURSE_KEY = SlashSeparatedCourseKey('org', 'course', 'run')
|
||||
STATIC_SOURCE = '"/static/file.png"'
|
||||
|
||||
|
||||
def encode_unicode_characters_in_url(url):
|
||||
"""
|
||||
Encodes all Unicode characters to their percent-encoding representation
|
||||
in both the path portion and query parameter portion of the given URL.
|
||||
"""
|
||||
scheme, netloc, path, params, query, fragment = urlparse(url)
|
||||
query_params = parse_qsl(query)
|
||||
updated_query_params = []
|
||||
for query_name, query_val in query_params:
|
||||
updated_query_params.append((query_name, urlquote(query_val)))
|
||||
|
||||
return urlunparse((scheme, netloc, urlquote(path, '/:+@'), params, urlencode(query_params), fragment))
|
||||
|
||||
|
||||
def test_multi_replace():
|
||||
course_source = '"/course/file.png"'
|
||||
|
||||
@@ -219,7 +202,7 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
cls.courses[prefix] = CourseFactory.create(org='a', course='b', run=prefix)
|
||||
|
||||
# Create an unlocked image.
|
||||
unlock_content = cls.create_image(prefix, (32, 32), 'blue', u'{}_ünlöck.png')
|
||||
unlock_content = cls.create_image(prefix, (32, 32), 'blue', '{}_unlock.png')
|
||||
|
||||
# Create a locked image.
|
||||
lock_content = cls.create_image(prefix, (32, 32), 'green', '{}_lock.png', locked=True)
|
||||
@@ -229,14 +212,14 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
contentstore().generate_thumbnail(lock_content, dimensions=(16, 16))
|
||||
|
||||
# Create an unlocked image in a subdirectory.
|
||||
cls.create_image(prefix, (1, 1), 'red', u'special/{}_ünlöck.png')
|
||||
cls.create_image(prefix, (1, 1), 'red', 'special/{}_unlock.png')
|
||||
|
||||
# Create a locked image in a subdirectory.
|
||||
cls.create_image(prefix, (1, 1), 'yellow', 'special/{}_lock.png', locked=True)
|
||||
|
||||
# Create an unlocked image with funky characters in the name.
|
||||
cls.create_image(prefix, (1, 1), 'black', u'weird {}_ünlöck.png')
|
||||
cls.create_image(prefix, (1, 1), 'black', u'special/weird {}_ünlöck.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')
|
||||
@@ -244,24 +227,6 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
cls.create_arbitrary_content(prefix, 'special/{}_not_excluded.htm')
|
||||
cls.create_arbitrary_content(prefix, 'special/{}_excluded.html')
|
||||
|
||||
@classmethod
|
||||
def get_content_digest_for_asset_path(cls, prefix, path):
|
||||
"""
|
||||
Takes an unprocessed asset path, parses it just enough to try and find the
|
||||
asset it refers to, and returns the content digest of that asset if it exists.
|
||||
"""
|
||||
|
||||
# Parse the path as if it was potentially a relative URL with query parameters,
|
||||
# or an absolute URL, etc. Only keep the path because that's all we need.
|
||||
_, _, relative_path, _, _, _ = urlparse(path)
|
||||
asset_key = StaticContent.get_asset_key_from_path(cls.courses[prefix].id, relative_path)
|
||||
|
||||
try:
|
||||
content = AssetManager.find(asset_key, as_stream=True)
|
||||
return content.content_digest
|
||||
except (ItemNotFoundError, NotFoundError):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def create_image(cls, prefix, dimensions, color, name, locked=False):
|
||||
"""
|
||||
@@ -312,100 +277,100 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
|
||||
@ddt.data(
|
||||
# No leading slash.
|
||||
(u'', u'{prfx}_ünlöck.png', u'/{asset}@{prfx}_ünlöck.png', 1),
|
||||
(u'', u'{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
|
||||
(u'', u'{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
|
||||
(u'', u'weird {prfx}_ünlöck.png', u'/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 1),
|
||||
(u'', u'weird {prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{asset}@{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 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.
|
||||
(u'', u'special/{prfx}_ünlöck.png', u'/{asset}@special_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'special/{prfx}_unlock.png', u'/{asset}@special_{prfx}_unlock.png', 1),
|
||||
(u'', u'special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
|
||||
(u'', u'special/weird {prfx}_ünlöck.png', u'/{asset}@special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'special/{prfx}_excluded.html', u'/{base_asset}@special_{prfx}_excluded.html', 1),
|
||||
(u'', u'special/weird {prfx}_unlock.png', u'/{asset}@special_weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{asset}@special_{prfx}_ünlöck.png', 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}_ünlöck.png', u'//dev/{asset}@special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'special/{prfx}_excluded.html', u'/{base_asset}@special_{prfx}_excluded.html', 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.
|
||||
(u'', u'/{prfx}_ünlöck.png', u'/{asset}@{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
|
||||
(u'', u'/{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
|
||||
(u'', u'/weird {prfx}_ünlöck.png', u'/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 1),
|
||||
(u'', u'/weird {prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{asset}@{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 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.
|
||||
(u'', u'/special/{prfx}_ünlöck.png', u'/{asset}@special_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/special/{prfx}_unlock.png', u'/{asset}@special_{prfx}_unlock.png', 1),
|
||||
(u'', u'/special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
|
||||
(u'', u'/special/weird {prfx}_ünlöck.png', u'/{asset}@special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/special/{prfx}_excluded.html', u'/{base_asset}@special_{prfx}_excluded.html', 1),
|
||||
(u'', u'/special/weird {prfx}_unlock.png', u'/{asset}@special_weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{asset}@special_{prfx}_ünlöck.png', 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}_ünlöck.png', u'//dev/{asset}@special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/special/{prfx}_excluded.html', u'/{base_asset}@special_{prfx}_excluded.html', 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.
|
||||
(u'', u'/static/{prfx}_ünlöck.png', u'/{asset}@{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
|
||||
(u'', u'/static/{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
|
||||
(u'', u'/static/weird {prfx}_ünlöck.png', u'/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 1),
|
||||
(u'', u'/static/weird {prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.png', 1),
|
||||
(u'', u'/static/{prfx}_excluded.html', u'/{asset}@{prfx}_excluded.html', 1),
|
||||
(u'', u'/static/{prfx}_not_excluded.htm', u'/{asset}@{prfx}_not_excluded.htm', 1),
|
||||
(u'dev', u'/static/{prfx}_ünlöck.png', u'//dev/{asset}@{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/static/{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 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.
|
||||
(u'', u'/static/special/{prfx}_ünlöck.png', u'/{asset}@special_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/special/{prfx}_unlock.png', u'/{asset}@special_{prfx}_unlock.png', 1),
|
||||
(u'', u'/static/special/{prfx}_lock.png', u'/{asset}@special_{prfx}_lock.png', 1),
|
||||
(u'', u'/static/special/weird {prfx}_ünlöck.png', u'/{asset}@special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/special/{prfx}_excluded.html', u'/{base_asset}@special_{prfx}_excluded.html', 1),
|
||||
(u'', u'/static/special/weird {prfx}_unlock.png', u'/{asset}@special_weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{asset}@special_{prfx}_ünlöck.png', 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}_ünlöck.png', u'//dev/{asset}@special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/static/special/{prfx}_excluded.html', u'/{base_asset}@special_{prfx}_excluded.html', 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.
|
||||
(
|
||||
u'',
|
||||
u'/static/{prfx}_ünlöck.png?foo=/static/{prfx}_lock.png',
|
||||
u'/{asset}@{prfx}_ünlöck.png?foo={encoded_asset}{prfx}_lock.png',
|
||||
u'/static/{prfx}_unlock.png?foo=/static/{prfx}_lock.png',
|
||||
u'/{asset}@{prfx}_unlock.png?foo={encoded_asset}{prfx}_lock.png',
|
||||
2
|
||||
),
|
||||
(
|
||||
u'',
|
||||
u'/static/{prfx}_lock.png?foo=/static/{prfx}_ünlöck.png',
|
||||
u'/{asset}@{prfx}_lock.png?foo={encoded_asset}{prfx}_ünlöck.png',
|
||||
u'/static/{prfx}_lock.png?foo=/static/{prfx}_unlock.png',
|
||||
u'/{asset}@{prfx}_lock.png?foo={encoded_asset}{prfx}_unlock.png',
|
||||
2
|
||||
),
|
||||
(
|
||||
u'',
|
||||
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html',
|
||||
u'/{base_asset}@{prfx}_excluded.html?foo={encoded_base_asset}{prfx}_excluded.html',
|
||||
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'/{base_asset}@{prfx}_excluded.html?foo={encoded_asset}{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_base_asset}{prfx}_excluded.html',
|
||||
u'/{asset}@{prfx}_not_excluded.htm?foo={encoded_asset}{prfx}_excluded.html',
|
||||
2
|
||||
),
|
||||
(
|
||||
@@ -416,32 +381,32 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
),
|
||||
(
|
||||
u'dev',
|
||||
u'/static/{prfx}_ünlöck.png?foo=/static/{prfx}_lock.png',
|
||||
u'//dev/{asset}@{prfx}_ünlöck.png?foo={encoded_asset}{prfx}_lock.png',
|
||||
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}_ünlöck.png',
|
||||
u'/{asset}@{prfx}_lock.png?foo={encoded_base_url}{encoded_asset}{prfx}_ünlöck.png',
|
||||
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
|
||||
),
|
||||
(
|
||||
u'dev',
|
||||
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html',
|
||||
u'/{base_asset}@{prfx}_excluded.html?foo={encoded_base_asset}{prfx}_excluded.html',
|
||||
u'/{asset}@{prfx}_excluded.html?foo={encoded_asset}{prfx}_excluded.html',
|
||||
2
|
||||
),
|
||||
(
|
||||
u'dev',
|
||||
u'/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm',
|
||||
u'/{base_asset}@{prfx}_excluded.html?foo={encoded_base_url}{encoded_asset}{prfx}_not_excluded.htm',
|
||||
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_base_asset}{prfx}_excluded.html',
|
||||
u'//dev/{asset}@{prfx}_not_excluded.htm?foo={encoded_asset}{prfx}_excluded.html',
|
||||
2
|
||||
),
|
||||
(
|
||||
@@ -451,189 +416,163 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
2
|
||||
),
|
||||
# Already asset key.
|
||||
(u'', u'/{base_asset}@{prfx}_ünlöck.png', u'/{asset}@{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{base_asset}@{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
|
||||
(u'', u'/{base_asset}@weird_{prfx}_ünlöck.png', u'/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{base_asset}@{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 1),
|
||||
(u'', u'/{base_asset}@{prfx}_not_excluded.htm', u'/{asset}@{prfx}_not_excluded.htm', 1),
|
||||
(u'dev', u'/{base_asset}@{prfx}_ünlöck.png', u'//dev/{asset}@{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/{base_asset}@{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
|
||||
(u'dev', u'/{base_asset}@weird_{prfx}_ünlöck.png', u'//dev/{asset}@weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/{base_asset}@{prfx}_excluded.html', u'/{base_asset}@{prfx}_excluded.html', 1),
|
||||
(u'dev', u'/{base_asset}@{prfx}_not_excluded.htm', u'//dev/{asset}@{prfx}_not_excluded.htm', 1),
|
||||
(u'', u'/{asset}@{prfx}_unlock.png', u'/{asset}@{prfx}_unlock.png', 1),
|
||||
(u'', u'/{asset}@{prfx}_lock.png', u'/{asset}@{prfx}_lock.png', 1),
|
||||
(u'', u'/{asset}@weird_{prfx}_unlock.png', u'/{asset}@weird_{prfx}_unlock.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.
|
||||
(u'', u'/{c4x}/{prfx}_ünlöck.png', u'/{c4x}/{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{c4x}/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
|
||||
(u'', u'/{c4x}/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
|
||||
(u'', u'/{c4x}/weird_{prfx}_lock.png', u'/{c4x}/weird_{prfx}_lock.png', 1),
|
||||
(u'', u'/{c4x}/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'/{c4x}/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
|
||||
(u'dev', u'/{c4x}/{prfx}_ünlöck.png', u'/{c4x}/{prfx}_ünlöck.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}_ünlöck.png', u'/{c4x}/weird_{prfx}_ünlöck.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.
|
||||
(u'', u'/{base_th_key}@{prfx}_ünlöck-{th_ext}', u'/{th_key}@{prfx}_ünlöck-{th_ext}', 1),
|
||||
(u'', u'/{base_th_key}@{prfx}_lock-{th_ext}', u'/{th_key}@{prfx}_lock-{th_ext}', 1),
|
||||
(u'dev', u'/{base_th_key}@{prfx}_ünlöck-{th_ext}', u'//dev/{th_key}@{prfx}_ünlöck-{th_ext}', 1),
|
||||
(u'dev', u'/{base_th_key}@{prfx}_lock-{th_ext}', u'//dev/{th_key}@{prfx}_lock-{th_ext}', 1),
|
||||
(u'', u'/{th_key}@{prfx}_unlock-{th_ext}', u'/{th_key}@{prfx}_unlock-{th_ext}', 1),
|
||||
(u'', u'/{th_key}@{prfx}_lock-{th_ext}', u'/{th_key}@{prfx}_lock-{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}@{prfx}_lock-{th_ext}', u'//dev/{th_key}@{prfx}_lock-{th_ext}', 1),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_canonical_asset_path_with_new_style_assets(self, base_url, start, expected, mongo_calls):
|
||||
exts = ['.html', '.tm']
|
||||
prefix = u'split'
|
||||
encoded_base_url = urlquote(u'//' + base_url)
|
||||
c4x = u'c4x/a/b/asset'
|
||||
base_asset_key = u'asset-v1:a+b+{}+type@asset+block'.format(prefix)
|
||||
adjusted_asset_key = base_asset_key
|
||||
encoded_asset_key = urlquote(u'/asset-v1:a+b+{}+type@asset+block@'.format(prefix))
|
||||
encoded_base_asset_key = encoded_asset_key
|
||||
base_th_key = u'asset-v1:a+b+{}+type@thumbnail+block'.format(prefix)
|
||||
adjusted_th_key = base_th_key
|
||||
th_ext = u'png-16x16.jpg'
|
||||
prefix = 'split'
|
||||
encoded_base_url = quote_plus('//' + base_url)
|
||||
c4x = 'c4x/a/b/asset'
|
||||
asset_key = 'asset-v1:a+b+{}+type@asset+block'.format(prefix)
|
||||
encoded_asset_key = quote_plus('/asset-v1:a+b+{}+type@asset+block@'.format(prefix))
|
||||
th_key = 'asset-v1:a+b+{}+type@thumbnail+block'.format(prefix)
|
||||
th_ext = 'png-16x16.jpg'
|
||||
|
||||
start = start.format(
|
||||
prfx=prefix,
|
||||
c4x=c4x,
|
||||
base_asset=base_asset_key,
|
||||
asset=adjusted_asset_key,
|
||||
asset=asset_key,
|
||||
encoded_base_url=encoded_base_url,
|
||||
encoded_asset=encoded_asset_key,
|
||||
base_th_key=base_th_key,
|
||||
th_key=adjusted_th_key,
|
||||
th_key=th_key,
|
||||
th_ext=th_ext
|
||||
)
|
||||
|
||||
# Adjust for content digest. This gets dicey quickly and we have to order our steps:
|
||||
# - replace format markets because they have curly braces
|
||||
# - encode Unicode characters to percent-encoded
|
||||
# - finally shove back in our regex patterns
|
||||
digest = CanonicalContentTest.get_content_digest_for_asset_path(prefix, start)
|
||||
if digest:
|
||||
adjusted_asset_key = u'assets/courseware/MARK/asset-v1:a+b+{}+type@asset+block'.format(prefix)
|
||||
adjusted_th_key = u'assets/courseware/MARK/asset-v1:a+b+{}+type@thumbnail+block'.format(prefix)
|
||||
encoded_asset_key = u'/assets/courseware/MARK/asset-v1:a+b+{}+type@asset+block@'.format(prefix)
|
||||
encoded_asset_key = urlquote(encoded_asset_key)
|
||||
|
||||
expected = expected.format(
|
||||
prfx=prefix,
|
||||
c4x=c4x,
|
||||
base_asset=base_asset_key,
|
||||
asset=adjusted_asset_key,
|
||||
asset=asset_key,
|
||||
encoded_base_url=encoded_base_url,
|
||||
encoded_asset=encoded_asset_key,
|
||||
base_th_key=base_th_key,
|
||||
th_key=adjusted_th_key,
|
||||
th_ext=th_ext,
|
||||
encoded_base_asset=encoded_base_asset_key,
|
||||
th_key=th_key,
|
||||
th_ext=th_ext
|
||||
)
|
||||
|
||||
expected = encode_unicode_characters_in_url(expected)
|
||||
expected = expected.replace('MARK', '[a-f0-9]{32}')
|
||||
expected = expected.replace('+', r'\+').replace('?', r'\?')
|
||||
|
||||
with check_mongo_calls(mongo_calls):
|
||||
asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url, exts)
|
||||
print expected
|
||||
print asset_path
|
||||
self.assertIsNotNone(re.match(expected, asset_path))
|
||||
self.assertEqual(asset_path, expected)
|
||||
|
||||
@ddt.data(
|
||||
# No leading slash.
|
||||
(u'', u'{prfx}_ünlöck.png', u'/{c4x}/{prfx}_ünlöck.png', 1),
|
||||
(u'', u'{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
|
||||
(u'', u'{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
|
||||
(u'', u'weird {prfx}_ünlöck.png', u'/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'weird {prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{c4x}/{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 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.
|
||||
(u'', u'special/{prfx}_ünlöck.png', u'/{c4x}/special_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'special/{prfx}_unlock.png', u'/{c4x}/special_{prfx}_unlock.png', 1),
|
||||
(u'', u'special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
|
||||
(u'', u'special/weird {prfx}_ünlöck.png', u'/{c4x}/special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'special/{prfx}_excluded.html', u'/{base_c4x}/special_{prfx}_excluded.html', 1),
|
||||
(u'', u'special/weird {prfx}_unlock.png', u'/{c4x}/special_weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{c4x}/special_{prfx}_ünlöck.png', 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}_ünlöck.png', u'//dev/{c4x}/special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'special/{prfx}_excluded.html', u'/{base_c4x}/special_{prfx}_excluded.html', 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.
|
||||
(u'', u'/{prfx}_ünlöck.png', u'/{c4x}/{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
|
||||
(u'', u'/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
|
||||
(u'', u'/weird {prfx}_ünlöck.png', u'/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'/weird {prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{c4x}/{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 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.
|
||||
(u'', u'/special/{prfx}_ünlöck.png', u'/{c4x}/special_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/special/{prfx}_unlock.png', u'/{c4x}/special_{prfx}_unlock.png', 1),
|
||||
(u'', u'/special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
|
||||
(u'', u'/special/weird {prfx}_ünlöck.png', u'/{c4x}/special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/special/{prfx}_excluded.html', u'/{base_c4x}/special_{prfx}_excluded.html', 1),
|
||||
(u'', u'/special/weird {prfx}_unlock.png', u'/{c4x}/special_weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{c4x}/special_{prfx}_ünlöck.png', 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}_ünlöck.png', u'//dev/{c4x}/special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/special/{prfx}_excluded.html', u'/{base_c4x}/special_{prfx}_excluded.html', 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.
|
||||
(u'', u'/static/{prfx}_ünlöck.png', u'/{c4x}/{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
|
||||
(u'', u'/static/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
|
||||
(u'', u'/static/weird {prfx}_ünlöck.png', u'/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'/static/weird {prfx}_unlock.png', u'/{c4x}/weird_{prfx}_unlock.png', 1),
|
||||
(u'', u'/static/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'/static/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
|
||||
(u'dev', u'/static/{prfx}_ünlöck.png', u'//dev/{c4x}/{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/static/{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 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.
|
||||
(u'', u'/static/special/{prfx}_ünlöck.png', u'/{c4x}/special_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/special/{prfx}_unlock.png', u'/{c4x}/special_{prfx}_unlock.png', 1),
|
||||
(u'', u'/static/special/{prfx}_lock.png', u'/{c4x}/special_{prfx}_lock.png', 1),
|
||||
(u'', u'/static/special/weird {prfx}_ünlöck.png', u'/{c4x}/special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/static/special/{prfx}_excluded.html', u'/{base_c4x}/special_{prfx}_excluded.html', 1),
|
||||
(u'', u'/static/special/weird {prfx}_unlock.png', u'/{c4x}/special_weird_{prfx}_unlock.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}_ünlöck.png', u'//dev/{c4x}/special_{prfx}_ünlöck.png', 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}_ünlöck.png', u'//dev/{c4x}/special_weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/static/special/{prfx}_excluded.html', u'/{base_c4x}/special_{prfx}_excluded.html', 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.
|
||||
(
|
||||
u'',
|
||||
u'/static/{prfx}_ünlöck.png?foo=/static/{prfx}_lock.png',
|
||||
u'/{c4x}/{prfx}_ünlöck.png?foo={encoded_c4x}{prfx}_lock.png',
|
||||
u'/static/{prfx}_unlock.png?foo=/static/{prfx}_lock.png',
|
||||
u'/{c4x}/{prfx}_unlock.png?foo={encoded_c4x}{prfx}_lock.png',
|
||||
2
|
||||
),
|
||||
(
|
||||
u'',
|
||||
u'/static/{prfx}_lock.png?foo=/static/{prfx}_ünlöck.png',
|
||||
u'/{c4x}/{prfx}_lock.png?foo={encoded_c4x}{prfx}_ünlöck.png',
|
||||
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'/{base_c4x}/{prfx}_excluded.html?foo={encoded_base_c4x}{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'/{base_c4x}/{prfx}_excluded.html?foo={encoded_c4x}{prfx}_not_excluded.htm',
|
||||
u'/{c4x}/{prfx}_excluded.html?foo={encoded_c4x}{prfx}_not_excluded.htm',
|
||||
2
|
||||
),
|
||||
(
|
||||
u'',
|
||||
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html',
|
||||
u'/{c4x}/{prfx}_not_excluded.htm?foo={encoded_base_c4x}{prfx}_excluded.html',
|
||||
u'/{c4x}/{prfx}_not_excluded.htm?foo={encoded_c4x}{prfx}_excluded.html',
|
||||
2
|
||||
),
|
||||
(
|
||||
@@ -644,32 +583,32 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
),
|
||||
(
|
||||
u'dev',
|
||||
u'/static/{prfx}_ünlöck.png?foo=/static/{prfx}_lock.png',
|
||||
u'//dev/{c4x}/{prfx}_ünlöck.png?foo={encoded_c4x}{prfx}_lock.png',
|
||||
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}_ünlöck.png',
|
||||
u'/{c4x}/{prfx}_lock.png?foo={encoded_base_url}{encoded_c4x}{prfx}_ünlöck.png',
|
||||
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'/{base_c4x}/{prfx}_excluded.html?foo={encoded_base_c4x}{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'/{base_c4x}/{prfx}_excluded.html?foo={encoded_base_url}{encoded_c4x}{prfx}_not_excluded.htm',
|
||||
u'/{c4x}/{prfx}_excluded.html?foo={encoded_base_url}{encoded_c4x}{prfx}_not_excluded.htm',
|
||||
2
|
||||
),
|
||||
(
|
||||
u'dev',
|
||||
u'/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html',
|
||||
u'//dev/{c4x}/{prfx}_not_excluded.htm?foo={encoded_base_c4x}{prfx}_excluded.html',
|
||||
u'//dev/{c4x}/{prfx}_not_excluded.htm?foo={encoded_c4x}{prfx}_excluded.html',
|
||||
2
|
||||
),
|
||||
(
|
||||
@@ -679,58 +618,38 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
2
|
||||
),
|
||||
# Old, c4x-style path.
|
||||
(u'', u'/{c4x}/{prfx}_ünlöck.png', u'/{c4x}/{prfx}_ünlöck.png', 1),
|
||||
(u'', u'/{c4x}/{prfx}_unlock.png', u'/{c4x}/{prfx}_unlock.png', 1),
|
||||
(u'', u'/{c4x}/{prfx}_lock.png', u'/{c4x}/{prfx}_lock.png', 1),
|
||||
(u'', u'/{c4x}/weird_{prfx}_lock.png', u'/{c4x}/weird_{prfx}_lock.png', 1),
|
||||
(u'', u'/{c4x}/{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'/{c4x}/{prfx}_excluded.html', u'/{c4x}/{prfx}_excluded.html', 1),
|
||||
(u'', u'/{c4x}/{prfx}_not_excluded.htm', u'/{c4x}/{prfx}_not_excluded.htm', 1),
|
||||
(u'dev', u'/{c4x}/{prfx}_ünlöck.png', u'//dev/{c4x}/{prfx}_ünlöck.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}_ünlöck.png', u'//dev/{c4x}/weird_{prfx}_ünlöck.png', 1),
|
||||
(u'dev', u'/{c4x}/{prfx}_excluded.html', u'/{base_c4x}/{prfx}_excluded.html', 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
|
||||
def test_canonical_asset_path_with_c4x_style_assets(self, base_url, start, expected, mongo_calls):
|
||||
exts = ['.html', '.tm']
|
||||
prefix = 'old'
|
||||
base_c4x_block = 'c4x/a/b/asset'
|
||||
adjusted_c4x_block = base_c4x_block
|
||||
encoded_c4x_block = urlquote('/' + base_c4x_block + '/')
|
||||
encoded_base_url = urlquote('//' + base_url)
|
||||
encoded_base_c4x_block = encoded_c4x_block
|
||||
c4x_block = 'c4x/a/b/asset'
|
||||
encoded_c4x_block = quote_plus('/' + c4x_block + '/')
|
||||
encoded_base_url = quote_plus('//' + base_url)
|
||||
|
||||
start = start.format(
|
||||
prfx=prefix,
|
||||
encoded_base_url=encoded_base_url,
|
||||
c4x=base_c4x_block,
|
||||
c4x=c4x_block,
|
||||
encoded_c4x=encoded_c4x_block
|
||||
)
|
||||
|
||||
# Adjust for content digest. This gets dicey quickly and we have to order our steps:
|
||||
# - replace format markets because they have curly braces
|
||||
# - encode Unicode characters to percent-encoded
|
||||
# - finally shove back in our regex patterns
|
||||
digest = CanonicalContentTest.get_content_digest_for_asset_path(prefix, start)
|
||||
if digest:
|
||||
adjusted_c4x_block = 'assets/courseware/MARK/c4x/a/b/asset'
|
||||
encoded_c4x_block = urlquote('/' + adjusted_c4x_block + '/')
|
||||
|
||||
expected = expected.format(
|
||||
prfx=prefix,
|
||||
encoded_base_url=encoded_base_url,
|
||||
base_c4x=base_c4x_block,
|
||||
c4x=adjusted_c4x_block,
|
||||
encoded_c4x=encoded_c4x_block,
|
||||
encoded_base_c4x=encoded_base_c4x_block,
|
||||
c4x=c4x_block,
|
||||
encoded_c4x=encoded_c4x_block
|
||||
)
|
||||
|
||||
expected = encode_unicode_characters_in_url(expected)
|
||||
expected = expected.replace('MARK', '[a-f0-9]{32}')
|
||||
expected = expected.replace('+', r'\+').replace('?', r'\?')
|
||||
|
||||
with check_mongo_calls(mongo_calls):
|
||||
asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url, exts)
|
||||
print expected
|
||||
print asset_path
|
||||
self.assertIsNotNone(re.match(expected, asset_path))
|
||||
self.assertEqual(asset_path, expected)
|
||||
|
||||
Reference in New Issue
Block a user