8000 feature #35762 [Asset] Allows to download asset manifest over HTTP (G… · symfony/asset@cccb535 · GitHub
[go: up one dir, main page]

Skip to content

Commit cccb535

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 ------- 4ba12a80e5 [Asset] Allows to download json manifest from a remote url
2 parents 5712486 + 6436d30 commit cccb535

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

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+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"symfony/http-foundation": ""
2323
},
2424
"require-dev": {
25+
"symfony/http-client": "^4.4|^5.0",
2526
"symfony/http-foundation": "^4.4|^5.0",
2627
"symfony/http-kernel": "^4.4|^5.0"
2728
},

0 commit comments

Comments
 (0)
0