Skip to content

Commit 6e95b8b

Browse files
committed
feature #46514 [HttpKernel] Add option to render Surrogate fragment with absolute URIs (Kern046)
This PR was merged into the 6.2 branch. Discussion ---------- [HttpKernel] Add option to render Surrogate fragment with absolute URIs | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | | License | MIT | Doc PR | Context ------- Using ESI blocks with Cloudflare Workers we faced an issue with the `/_fragment` relative URIs, as Cloudflare didn't succeed to handle it. We needed the absolute URL to make it work. Proposed solution -------- In Symfony's codebase I noticed that `Symfony\Component\HttpKernel\Fragment\FragmentUriGenerator::generate` already supports a `$absolute` parameter to fit the needs of `fragment_uri` Twig function (I even wonder if this wasn't a previously supported feature when I see #8879), but this parameter couldn't be set through `render_esi`. This PR adds the support of a new `absolute_uri` option in order to set this parameter and get an absolute URI for ESI and SSI fragments. It only applies when using a `ControllerReference` as the URI or `alt` option. It defaults to `false` to avoid causing any BC break. ### Naming I am not that confident about the naming: - I used `absolute_uri` for the option to keep it more self-descriptive than just `absolute`. - I used `$absolute` to keep it more consistent with the existing parameters and usage in `HttpKernelRuntime::generateFragmentUri`. I have doubts about the pertinence of such a diff between the option and the variable name. Let me know what you think about it ! Commits ------- f9f3ed0 [HttpKernel] Add option to render Surrogate fragment with absolute URIs
2 parents 4811813 + f9f3ed0 commit 6e95b8b

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add constructor argument `bool $catchThrowable` to `HttpKernel`
88
* Add `ControllerEvent::getAttributes()` to handle attributes on controllers
99
* Add `#[Cache]` to describe the default HTTP cache headers on controllers
10+
* Add `absolute_uri` option to surrogate fragment renderers
1011

1112
6.1
1213
---

src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function __construct(SurrogateInterface $surrogate = null, FragmentRender
5151
*
5252
* * alt: an alternative URI to render in case of an error
5353
* * comment: a comment to add when returning the surrogate tag
54+
* * absolute_uri: whether to generate an absolute URI or not. Default is false
5455
*
5556
* Note, that not all surrogate strategies support all options. For now
5657
* 'alt' and 'comment' are only supported by ESI.
@@ -67,23 +68,25 @@ public function render(string|ControllerReference $uri, Request $request, array
6768
return $this->inlineStrategy->render($uri, $request, $options);
6869
}
6970

71+
$absolute = $options['absolute_uri'] ?? false;
72+
7073
if ($uri instanceof ControllerReference) {
71-
$uri = $this->generateSignedFragmentUri($uri, $request);
74+
$uri = $this->generateSignedFragmentUri($uri, $request, $absolute);
7275
}
7376

7477
$alt = $options['alt'] ?? null;
7578
if ($alt instanceof ControllerReference) {
76-
$alt = $this->generateSignedFragmentUri($alt, $request);
79+
$alt = $this->generateSignedFragmentUri($alt, $request, $absolute);
7780
}
7881

7982
$tag = $this->surrogate->renderIncludeTag($uri, $alt, $options['ignore_errors'] ?? false, $options['comment'] ?? '');
8083

8184
return new Response($tag);
8285
}
8386

84-
private function generateSignedFragmentUri(ControllerReference $uri, Request $request): string
87+
private function generateSignedFragmentUri(ControllerReference $uri, Request $request, bool $absolute): string
8588
{
86-
return (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request);
89+
return (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request, $absolute);
8790
}
8891

8992
private function containsNonScalars(array $values): bool

src/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,24 @@ public function testRenderControllerReference()
6666
);
6767
}
6868

69+
public function testRenderControllerReferenceWithAbsoluteUri()
70+
{
71+
$signer = new UriSigner('foo');
72+
$strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(), $signer);
73+
74+
$request = Request::create('http://localhost/');
75+
$request->setLocale('fr');
76+
$request->headers->set('Surrogate-Capability', 'ESI/1.0');
77+
78+
$reference = new ControllerReference('main_controller', [], []);
79+
$altReference = new ControllerReference('alt_controller', [], []);
80+
81+
$this->assertSame(
82+
'<esi:include src="http://localhost/_fragment?_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D&_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller" alt="http://localhost/_fragment?_hash=iPJEdRoUpGrM1ztqByiorpfMPtiW%2FOWwdH1DBUXHhEc%3D&_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dalt_controller" />',
83+
$strategy->render($reference, $request, ['alt' => $altReference, 'absolute_uri' => true])->getContent()
84+
);
85+
}
86+
6987
public function testRenderControllerReferenceWithoutSignerThrowsException()
7088
{
7189
$this->expectException(\LogicException::class);

src/Symfony/Component/HttpKernel/Tests/Fragment/SsiFragmentRendererTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,24 @@ public function testRenderControllerReference()
5757
);
5858
}
5959

60+
public function testRenderControllerReferenceWithAbsoluteUri()
61+
{
62+
$signer = new UriSigner('foo');
63+
$strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy(), $signer);
64+
65+
$request = Request::create('http://localhost/');
66+
$request->setLocale('fr');
67+
$request->headers->set('Surrogate-Capability', 'SSI/1.0');
68+
69+
$reference = new ControllerReference('main_controller', [], []);
70+
$altReference = new ControllerReference('alt_controller', [], []);
71+
72+
$this->assertSame(
73+
'<!--#include virtual="http://localhost/_fragment?_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D&_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller" -->',
74+
$strategy->render($reference, $request, ['alt' => $altReference, 'absolute_uri' => true])->getContent()
75+
);
76+
}
77+
6078
public function testRenderControllerReferenceWithoutSignerThrowsException()
6179
{
6280
$this->expectException(\LogicException::class);

0 commit comments

Comments
 (0)