8000 [Asset] Allows to download json manifest from a remote url · symfony/symfony@4ba12a8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4ba12a8

Browse files
committed
[Asset] Allows to download json manifest from a remote url
Handle URL in json_manifest_path Download the manifest using the HttpClient
1 parent 7995fed commit 4ba12a8

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
@@ -1049,7 +1049,12 @@ private function createVersion(ContainerBuilder $container, ?string $version, ?s
10491049
}
10501050

10511051
if (null !== $jsonManifestPath) {
1052-
$def = new ChildDefinition('assets.json_manifest_version_strategy');
1052+
$definitionName = 'assets.json_manifest_version_strategy';
1053+
if (0 === strpos(parse_url($jsonManifestPath, PHP_URL_SCHEME), 'http')) {
1054+
$definitionName = 'assets.remote_json_manifest_version_strategy';
1055+
}
1056+
1057+
$def = new ChildDefinition($definitionName);
10531058
$def->replaceArgument(0, $jsonManifestPath);
10541059
$container->setDefinition('assets._version_'.$name, $def);
10551060

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& 67ED #39; => [
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
@@ -32,7 +32,7 @@
3232
"require-dev": {
3333
"doctrine/annotations": "~1.7",
3434
"doctrine/cache": "~1.0",
35-
"symfony/asset": "^4.4|^5.0",
35+
"symfony/asset": "^5.1",
3636
"symfony/browser-kit": "^4.4|^5.0",
3737
"symfony/console": "^4.4|^5.0",
3838
"symfony/css-selector": "^4.4|^5.0",
@@ -68,7 +68,7 @@
6868
"phpdocumentor/reflection-docblock": "<3.0",
6969
"phpdocumentor/type-resolver": "<0.2.1",
7070
"phpunit/phpunit": "<5.4.3",
71-
"symfony/asset": "<4.4",
71+
"symfony/asset": "<5.1",
7272
"symfony/browser-kit": "<4.4",
7373
"symfony/console": "<4.4",
7474
"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)
0