diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 87d722b91e4d..854746e39262 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -573,6 +573,7 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
->end()
->prototype('scalar')->end()
->end()
+ ->scalarNode('is_strict_protocol')->defaultValue(false)->end()
->end()
->validate()
->ifTrue(function ($v) {
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index c65c1f8e740b..1d39b9c4b2ab 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -883,7 +883,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
$defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default');
}
- $defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion);
+ $defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion, false);
$container->setDefinition('assets._default_package', $defaultPackage);
$namedPackages = array();
@@ -900,7 +900,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
$version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name);
}
- $container->setDefinition('assets._package_'.$name, $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version));
+ $container->setDefinition('assets._package_'.$name, $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version, $package['is_strict_protocol']));
$namedPackages[$name] = new Reference('assets._package_'.$name);
}
@@ -913,7 +913,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
/**
* Returns a definition for an asset package.
*/
- private function createPackageDefinition($basePath, array $baseUrls, Reference $version)
+ private function createPackageDefinition($basePath, array $baseUrls, Reference $version, $isStrictProtocol)
{
if ($basePath && $baseUrls) {
throw new \LogicException('An asset package cannot have base URLs and base paths.');
@@ -926,6 +926,10 @@ private function createPackageDefinition($basePath, array $baseUrls, Reference $
->replaceArgument(1, $version)
;
+ if ($baseUrls) {
+ $package->replaceArgument(3, $isStrictProtocol);
+ }
+
return $package;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index 29d07c5758ee..f2d5b74b4915 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -150,6 +150,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
index dc6bf7bb8df5..e7e653acc37f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
@@ -27,6 +27,10 @@
'json_manifest_strategy' => array(
'json_manifest_path' => '/path/to/manifest.json',
),
+ 'strict_protocol' => array(
+ 'is_strict_protocol' => true,
+ 'base_urls' => array('http://www.example.com', 'https://www.example.net'),
+ ),
),
),
));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
index a907a5b967f9..01dda342178d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
@@ -22,6 +22,10 @@
https://bar_version_strategy.example.com
+
+ http://www.example.com
+ https://www.example.net
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
index a1679e389ddb..be70de4b30b4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
@@ -19,3 +19,6 @@ framework:
version_strategy: assets.custom_version_strategy
json_manifest_strategy:
json_manifest_path: '/path/to/manifest.json'
+ strict_protocol:
+ base_urls: ["http://www.example.com", "https://www.example.net"]
+ is_strict_protocol: true
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index 4f86c85d4f8f..1965b0a38b09 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -380,23 +380,23 @@ public function testAssets()
// default package
$defaultPackage = $container->getDefinition((string) $packages->getArgument(0));
- $this->assertUrlPackage($container, $defaultPackage, array('http://cdn.example.com'), 'SomeVersionScheme', '%%s?version=%%s');
+ $this->assertUrlPackage($container, $defaultPackage, array('http://cdn.example.com'), 'SomeVersionScheme', '%%s?version=%%s', false);
// packages
$packages = $packages->getArgument(1);
- $this->assertCount(6, $packages);
+ $this->assertCount(7, $packages);
$package = $container->getDefinition((string) $packages['images_path']);
$this->assertPathPackage($container, $package, '/foo', 'SomeVersionScheme', '%%s?version=%%s');
$package = $container->getDefinition((string) $packages['images']);
- $this->assertUrlPackage($container, $package, array('http://images1.example.com', 'http://images2.example.com'), '1.0.0', '%%s?version=%%s');
+ $this->assertUrlPackage($container, $package, array('http://images1.example.com', 'http://images2.example.com'), '1.0.0', '%%s?version=%%s', false);
$package = $container->getDefinition((string) $packages['foo']);
$this->assertPathPackage($container, $package, '', '1.0.0', '%%s-%%s');
$package = $container->getDefinition((string) $packages['bar']);
- $this->assertUrlPackage($container, $package, array('https://bar2.example.com'), 'SomeVersionScheme', '%%s?version=%%s');
+ $this->assertUrlPackage($container, $package, array('https://bar2.example.com'), 'SomeVersionScheme', '%%s?version=%%s', false);
$package = $container->getDefinition((string) $packages['bar_version_strategy']);
$this->assertEquals('assets.custom_version_strategy', (string) $package->getArgument(1));
@@ -405,6 +405,9 @@ public function testAssets()
$versionStrategy = $container->getDefinition((string) $package->getArgument(1));
$this->assertEquals('assets.json_manifest_version_strategy', $versionStrategy->getParent());
$this->assertEquals('/path/to/manifest.json', $versionStrategy->getArgument(0));
+
+ $package = $container->getDefinition((string) $packages['strict_protocol']);
+ $this->assertUrlPackage($container, $package, array('http://www.example.com', 'https://www.example.net'), 'SomeVersionScheme', '%%s?version=%%s', true);
}
public function testAssetsDefaultVersionStrategyAsService()
@@ -994,10 +997,11 @@ private function assertPathPackage(ContainerBuilder $container, ChildDefinition
$this->assertVersionStrategy($container, $package->getArgument(1), $version, $format);
}
- private function assertUrlPackage(ContainerBuilder $container, ChildDefinition $package, $baseUrls, $version, $format)
+ private function assertUrlPackage(ContainerBuilder $container, ChildDefinition $package, $baseUrls, $version, $format, $isStrictProtocol)
{
$this->assertEquals('assets.url_package', $package->getParent());
$this->assertEquals($baseUrls, $package->getArgument(0));
+ $this->assertEquals($isStrictProtocol, $package->getArgument(3));
$this->assertVersionStrategy($container, $package->getArgument(1), $version, $format);
}
diff --git a/src/Symfony/Component/Asset/Tests/UrlPackageTest.php b/src/Symfony/Component/Asset/Tests/UrlPackageTest.php
index 97e7a46d706d..a8a59fd7da65 100644
--- a/src/Symfony/Component/Asset/Tests/UrlPackageTest.php
+++ b/src/Symfony/Component/Asset/Tests/UrlPackageTest.php
@@ -74,6 +74,37 @@ public function getContextConfigs()
array(true, array('http://example.com'), '', 'foo', 'http://example.com/foo?v1'),
array(true, array('http://example.com', 'https://example.com'), '', 'foo', 'https://example.com/foo?v1'),
+ array(true, array('https://example.com', 'https://example.net'), '', 'foo', 'https://example.com/foo?v1'),
+ array(true, array('https://example.com', 'https://example.net'), '', 'fooa', 'https://example.net/fooa?v1'),
+ );
+ }
+
+ /**
+ * @dataProvider getStrictUrlConfigs
+ */
+ public function testGetUrlWithStrictUrl($secure, $baseUrls, $format, $path, $expected)
+ {
+ $package = new UrlPackage($baseUrls, new StaticVersionStrategy('v1', $format), $this->getContext($secure), true);
+
+ $this->assertEquals($expected, $package->getUrl($path));
+ }
+
+ public function getStrictUrlConfigs()
+ {
+ return array(
+ array(false, array('http://example.com', 'http://example.net', 'https://example.com', 'https://example.net'), '', 'foo', 'http://example.com/foo?v1'),
+ array(false, array('http://example.com', 'http://example.net', 'https://example.com', 'https://example.net'), '', 'fooa', 'http://example.net/fooa?v1'),
+
+ array(true, array('http://example.com', 'http://example.net', 'https://example.com', 'https://example.net'), '', 'foo', 'https://example.com/foo?v1'),
+ array(true, array('http://example.com', 'http://example.net', 'https://example.com', 'https://example.net'), '', 'fooa', 'https://example.net/fooa?v1'),
+
+ array(false, array('//example.com', 'http://example.com', 'https://example.com'), '', 'foo', '//example.com/foo?v1'),
+ array(false, array('//example.com', 'http://example.com', 'https://example.com'), '', 'fooa', 'http://example.com/fooa?v1'),
+
+ array(true, array('//example.com', 'http://example.com', 'https://example.com'), '', 'foo', '//example.com/foo?v1'),
+ array(true, array('//example.com', 'http://example.com', 'https://example.com'), '', 'fooa', 'https://example.com/fooa?v1'),
+
+ array(false, array('https://example.com', 'https://example.net'), '', 'foo', 'https://example.com/foo?v1'),
);
}
diff --git a/src/Symfony/Component/Asset/UrlPackage.php b/src/Symfony/Component/Asset/UrlPackage.php
index 782b2ddfce93..9205eab89f14 100644
--- a/src/Symfony/Component/Asset/UrlPackage.php
+++ b/src/Symfony/Component/Asset/UrlPackage.php
@@ -27,7 +27,10 @@
* When the request context is available, this package can choose the
* best base URL to use based on the current request scheme:
*
- * * For HTTP request, it chooses between all base URLs;
+ * * For HTTP request:
+ * * if $isStrictProtocol is set to false, it chooses between all base URLs
+ * * if $isStrictProtocol is set to true, it will only use HTTP base URLs and relative protocol URLs
+ * or falls back to any base URL if no secure ones are available;
* * For HTTPs requests, it chooses between HTTPs base URLs and relative protocol URLs
* or falls back to any base URL if no secure ones are available.
*
@@ -35,15 +38,28 @@
*/
class UrlPackage extends Package
{
+ /** @var array $baseUrls */
private $baseUrls = array();
- private $sslPackage;
+
+ /** @var string[] $baseSecureUrls */
+ private $baseSecureUrls = array();
+
+ /** @var string[] $baseUnsecureUrls */
+ private $baseInsecureUrls = array();
+
+ /** @var string[] $baseFullUrls */
+ private $baseFullUrls = array();
+
+ /** @var bool $isStrictProtocol */
+ private $isStrictProtocol;
/**
- * @param string|string[] $baseUrls Base asset URLs
- * @param VersionStrategyInterface $versionStrategy The version strategy
- * @param ContextInterface|null $context Context
+ * @param string|string[] $baseUrls Base asset URLs
+ * @param VersionStrategyInterface $versionStrategy The version strategy
+ * @param ContextInterface|null $context Context
+ * @param bool $isStrictProtocol Is http strict, or does it allow https on http pages
*/
- public function __construct($baseUrls, VersionStrategyInterface $versionStrategy, ContextInterface $context = null)
+ public function __construct($baseUrls, VersionStrategyInterface $versionStrategy, ContextInterface $context = null, $isStrictProtocol = false)
{
parent::__construct($versionStrategy, $context);
@@ -59,11 +75,9 @@ public function __construct($baseUrls, VersionStrategyInterface $versionStrategy
$this->baseUrls[] = rtrim($baseUrl, '/');
}
- $sslUrls = $this->getSslUrls($baseUrls);
+ $this->isStrictProtocol = $isStrictProtocol;
- if ($sslUrls && $baseUrls !== $sslUrls) {
- $this->sslPackage = new self($sslUrls, $versionStrategy);
- }
+ $this->prepareBaseUrl($this->baseUrls);
}
/**
@@ -75,10 +89,6 @@ public function getUrl($path)
return $path;
}
- if (null !== $this->sslPackage && $this->getContext()->isSecure()) {
- return $this->sslPackage->getUrl($path);
- }
-
$url = $this->getVersionStrategy()->applyVersion($path);
if ($this->isAbsoluteUrl($url)) {
@@ -105,6 +115,8 @@ public function getBaseUrl($path)
return $this->baseUrls[0];
}
+ $this->setCurrentBaseUrls();
+
return $this->baseUrls[$this->chooseBaseUrl($path)];
}
@@ -123,17 +135,44 @@ protected function chooseBaseUrl($path)
return (int) fmod(hexdec(substr(hash('sha256', $path), 0, 10)), count($this->baseUrls));
}
- private function getSslUrls($urls)
+ /**
+ * Set the baseUrls var depending on the context.
+ */
+ private function setCurrentBaseUrls()
{
- $sslUrls = array();
+ if (!empty($this->baseSecureUrls) && $this->getContext()->isSecure()) {
+ $this->baseUrls = $this->baseSecureUrls;
+ } elseif (!empty($this->baseInsecureUrls) && $this->isStrictProtocol) {
+ $this->baseUrls = $this->baseInsecureUrls;
+ } else {
+ $this->baseUrls = $this->baseFullUrls;
+ }
+ }
+
+ /**
+ * Split urls in three categories: secure urls, unsecure urls and all urls
+ * Some url can be found in both secure & insecure categories (// & https depending on $isStrictProtocol option).
+ *
+ * @param array $urls
+ */
+ private function prepareBaseUrl(array $urls)
+ {
+ $this->baseFullUrls = $urls;
+
foreach ($urls as $url) {
- if ('https://' === substr($url, 0, 8) || '//' === substr($url, 0, 2)) {
- $sslUrls[] = $url;
- } elseif ('http://' !== substr($url, 0, 7)) {
+ if ('https://' === substr($url, 0, 8)) {
+ $this->baseSecureUrls[] = $url;
+ if ($this->isStrictProtocol === false) {
+ $this->baseInsecureUrls[] = $url;
+ }
+ } elseif ('http://' === substr($url, 0, 7)) {
+ $this->baseInsecureUrls[] = $url;
+ } elseif ('//' === substr($url, 0, 2)) {
+ $this->baseInsecureUrls[] = $url;
+ $this->baseSecureUrls[] = $url;
+ } else {
throw new InvalidArgumentException(sprintf('"%s" is not a valid URL', $url));
}
}
-
- return $sslUrls;
}
}