Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add strict option for http url in asset #22510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
}

Expand All @@ -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.');
Expand All @@ -926,6 +926,10 @@ private function createPackageDefinition($basePath, array $baseUrls, Reference $
->replaceArgument(1, $version)
;

if ($baseUrls) {
$package->replaceArgument(3, $isStrictProtocol);
}

return $package;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
<xsd:attribute name="version" type="xsd:string" />
<xsd:attribute name="version-format" type="xsd:string" />
<xsd:attribute name="json-manifest-path" type="xsd:string" />
<xsd:attribute name="is-strict-protocol" type="xsd:boolean" />
</xsd:complexType>

<xsd:complexType name="templating">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
),
),
),
));
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
<framework:base-url>https://bar_version_strategy.example.com</framework:base-url>
</framework:package>
<framework:package name="json_manifest_strategy" json-manifest-path="/path/to/manifest.json" />
<framework:package name="strict_protocol" is-strict-protocol="true">
<framework:base-url>http://www.example.com</framework:base-url>
<framework:base-url>https://www.example.net</framework:base-url>
</framework:package>
</framework:assets>
</framework:config>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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()
Expand Down Expand Up @@ -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);
}

Expand Down
31 changes: 31 additions & 0 deletions src/Symfony/Component/Asset/Tests/UrlPackageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add a test case with a protocol-relative URL.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


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'),
);
}

Expand Down
81 changes: 60 additions & 21 deletions src/Symfony/Component/Asset/UrlPackage.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,39 @@
* 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.
*
* @author Fabien Potencier <[email protected]>
*/
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);

Expand All @@ -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);
}

/**
Expand All @@ -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)) {
Expand All @@ -105,6 +115,8 @@ public function getBaseUrl($path)
return $this->baseUrls[0];
}

$this->setCurrentBaseUrls();

return $this->baseUrls[$this->chooseBaseUrl($path)];
}

Expand All @@ -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;
}
}