Skip to content

Commit 0647508

Browse files
feature #35762 [Asset] Allows to download asset manifest over HTTP (GromNaN)
This PR was merged into the 5.1-dev branch. Discussion ---------- [Asset] Allows to download asset manifest over HTTP | Q | A | ------------- | --- | Branch? | master <!-- see below --> | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #35761 Fix #33001 | License | MIT | Doc PR | symfony/symfony-docs#13255 ```yaml framework: assets: json_manifest_path: 'https://cdn.example.com/manifest.json' ``` Commits ------- 4ba12a8 [Asset] Allows to download json manifest from a remote url
2 parents 3b38f38 + 4ba12a8 commit 0647508

File tree

11 files changed

+166
-4
lines changed

11 files changed

+166
-4
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,12 @@ private function createVersion(ContainerBuilder $container, ?string $version, ?s
10571057
}
10581058

10591059
if (null !== $jsonManifestPath) {
1060-
$def = new ChildDefinition('assets.json_manifest_version_strategy');
1060+
$definitionName = 'assets.json_manifest_version_strategy';
1061+
if (0 === strpos(parse_url($jsonManifestPath, PHP_URL_SCHEME), 'http')) {
1062+
$definitionName = 'assets.remote_json_manifest_version_strategy';
1063+
}
1064+
1065+
$def = new ChildDefinition($definitionName);
10611066
$def->replaceArgument(0, $jsonManifestPath);
10621067
$container->setDefinition('assets._version_'.$name, $def);
10631068

src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,10 @@
5050
<service id="assets.json_manifest_version_strategy" class="Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy" abstract="true">
5151
<argument /> <!-- manifest path -->
5252
</service>
53+
54+
<service id="assets.remote_json_manifest_version_strategy" class="Symfony\Component\Asset\VersionStrategy\RemoteJsonManifestVersionStrategy" abstract="true">
55+
<argument /> <!-- manifest url -->
56+
<argument type="service" id="http_client" />
57+
</service>
5358
</services>
5459
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
'json_manifest_strategy' => [
2828
'json_manifest_path' => '/path/to/manifest.json',
2929
],
30+
'remote_manifest' => [
31+
'json_manifest_path' => 'https://cdn.example.com/manifest.json',
32+
],
3033
],
3134
],
3235
]);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<framework:base-url>https://bar_version_strategy.example.com</framework:base-url>
2323
</framework:package>
2424
<framework:package name="json_manifest_strategy" json-manifest-path="/path/to/manifest.json" />
25+
<framework:package name="remote_manifest" json-manifest-path="https://cdn.example.com/manifest.json" />
2526
</framework:assets>
2627
</framework:config>
2728
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ framework:
1919
version_strategy: assets.custom_version_strategy
2020
json_manifest_strategy:
2121
json_manifest_path: '/path/to/manifest.json'
22+
remote_manifest:
23+
json_manifest_path: 'https://cdn.example.com/manifest.json'

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ public function testAssets()
535535

536536
// packages
537537
$packages = $packages->getArgument(1);
538-
$this->assertCount(6, $packages);
538+
$this->assertCount(7, $packages);
539539

540540
$package = $container->getDefinition((string) $packages['images_path']);
541541
$this->assertPathPackage($container, $package, '/foo', 'SomeVersionScheme', '%%s?version=%%s');
@@ -556,6 +556,11 @@ public function testAssets()
556556
$versionStrategy = $container->getDefinition((string) $package->getArgument(1));
557557
$this->assertEquals('assets.json_manifest_version_strategy', $versionStrategy->getParent());
558558
$this->assertEquals('/path/to/manifest.json', $versionStrategy->getArgument(0));
559+
560+
$package = $container->getDefinition($packages['remote_manifest']);
561+
$versionStrategy = $container->getDefinition($package->getArgument(1));
562+
$this->assertSame('assets.remote_json_manifest_version_strategy', $versionStrategy->getParent());
563+
$this->assertSame('https://cdn.example.com/manifest.json', $versionStrategy->getArgument(0));
559564
}
560565

561566
public function testAssetsDefaultVersionStrategyAsService()

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"require-dev": {
3434
"doctrine/annotations": "~1.7",
3535
"doctrine/cache": "~1.0",
36-
"symfony/asset": "^4.4|^5.0",
36+
"symfony/asset": "^5.1",
3737
"symfony/browser-kit": "^4.4|^5.0",
3838
"symfony/console": "^4.4|^5.0",
3939
"symfony/css-selector": "^4.4|^5.0",
@@ -70,7 +70,7 @@
7070
"phpdocumentor/reflection-docblock": "<3.0",
7171
"phpdocumentor/type-resolver": "<0.2.1",
7272
"phpunit/phpunit": "<5.4.3",
73-
"symfony/asset": "<4.4",
73+
"symfony/asset": "<5.1",
7474
"symfony/browser-kit": "<4.4",
7575
"symfony/console": "<4.4",
7676
"symfony/dotenv": "<5.1",

src/Symfony/Component/Asset/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* added `RemoteJsonManifestVersionStrategy` to download manifest over HTTP.
8+
49
4.2.0
510
-----
611

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Asset\Tests\VersionStrategy;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Asset\VersionStrategy\RemoteJsonManifestVersionStrategy;
16+
use Symfony\Component\HttpClient\Exception\JsonException;
17+
use Symfony\Component\HttpClient\MockHttpClient;
18+
use Symfony\Component\HttpClient\Response\MockResponse;
19+
20+
class RemoteJsonManifestVersionStrategyTest extends TestCase
21+
{
22+
public function testGetVersion()
23+
{
24+
$strategy = $this->createStrategy('https://cdn.example.com/manifest-valid.json');
25+
26+
$this->assertSame('main.123abc.js', $strategy->getVersion('main.js'));
27+
}
28+
29+
public function testApplyVersion()
30+
{
31+
$strategy = $this->createStrategy('https://cdn.example.com/manifest-valid.json');
32+
33+
$this->assertSame('css/styles.555def.css', $strategy->getVersion('css/styles.css'));
34+
}
35+
36+
public function testApplyVersionWhenKeyDoesNotExistInManifest()
37+
{
38+
$strategy = $this->createStrategy('https://cdn.example.com/manifest-valid.json');
39+
40+
$this->assertSame('css/other.css', $strategy->getVersion('css/other.css'));
41+
}
42+
43+
public function testMissingManifestFileThrowsException()
44+
{
45+
$this->expectException('RuntimeException');
46+
$this->expectExceptionMessage('HTTP 404 returned for "https://cdn.example.com/non-existent-file.json"');
47+
$strategy = $this->createStrategy('https://cdn.example.com/non-existent-file.json');
48+
$strategy->getVersion('main.js');
49+
}
50+
51+
public function testManifestFileWithBadJSONThrowsException()
52+
{
53+
$this->expectException(JsonException::class);
54+
$this->expectExceptionMessage('Syntax error');
55+
$strategy = $this->createStrategy('https://cdn.example.com/manifest-invalid.json');
56+
$strategy->getVersion('main.js');
57+
}
58+
59+
private function createStrategy($manifestUrl)
60+
{
61+
$httpClient = new MockHttpClient(function ($method, $url, $options) {
62+
$filename = __DIR__.'/../fixtures/'.basename($url);
63+
64+
if (file_exists($filename)) {
65+
return new MockResponse(file_get_contents($filename), ['http_headers' => ['content-type' => 'application/json']]);
66+
}
67+
68+
return new MockResponse('{}', ['http_code' => 404]);
69+
});
70+
71+
return new RemoteJsonManifestVersionStrategy($manifestUrl, $httpClient);
72+
}
73+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Asset\VersionStrategy;
13+
14+
use Symfony\Contracts\HttpClient\HttpClientInterface;
15+
16+
/**
17+
* Reads the versioned path of an asset from a remote JSON manifest file.
18+
*
19+
* For example, the manifest file might look like this:
20+
* {
21+
* "main.js": "main.abc123.js",
22+
* "css/styles.css": "css/styles.555abc.css"
23+
* }
24+
*
25+
* You could then ask for the version of "main.js" or "css/styles.css".
26+
*/
27+
class RemoteJsonManifestVersionStrategy implements VersionStrategyInterface
28+
{
29+
private $manifestData;
30+
private $manifestUrl;
31+
private $httpClient;
32+
33+
/**
34+
* @param string $manifestUrl Absolute URL to the manifest file
35+
*/
36+
public function __construct(string $manifestUrl, HttpClientInterface $httpClient)
37+
{
38+
$this->manifestUrl = $manifestUrl;
39+
$this->httpClient = $httpClient;
40+
}
41+
42+
/**
43+
* With a manifest, we don't really know or care about what
44+
* the version is. Instead, this returns the path to the
45+
* versioned file.
46+
*/
47+
public function getVersion(string $path)
48+
{
49+
return $this->applyVersion($path);
50+
}
51+
52+
public function applyVersion(string $path)
53+
{
54+
if (null === $this->manifestData) {
55+
$this->manifestData = $this->httpClient->request('GET', $this->manifestUrl, [
56+
'headers' => ['accept' => 'application/json'],
57+
])->toArray();
58+
}
59+
60+
return $this->manifestData[$path] ?? $path;
61+
}
62+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy