Skip to content

Commit ae21db7

Browse files
committed
feature #217 [Turbo] Simplify stream negotiation (dunglas)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [Turbo] Simplify stream negotiation | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Tickets | n/a | License | MIT This patch replaces the ad-hoc content negotiation system for Turbo Streams used by the bundle. HttpFoundation's native content negotiation features are now used instead. This greatly simplifies the code, which is security-sensitive, and improves DX (content negotiation is now consistent with how it is handled in the rest of the framework). Replaces #214. Needs #215 and symfony/symfony#44980. Commits ------- b6de1e3 [Turbo] Simplify stream negotiation
2 parents 39d4e49 + b6de1e3 commit ae21db7

File tree

7 files changed

+44
-106
lines changed

7 files changed

+44
-106
lines changed

src/Turbo/CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
# CHANGELOG
22

3+
## 2.1
4+
5+
- `TurboStreamResponse` and `AddTurboStreamFormatSubscriber` have been removed, use native content negotiation instead:
6+
7+
```php
8+
use Symfony\UX\Turbo\TurboBundle;
9+
10+
class TaskController extends AbstractController
11+
{
12+
public function new(Request $request): Response
13+
{
14+
// ...
15+
if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
16+
$request->setRequestFormat(TurboBundle::STREAM_FORMAT);
17+
$response = $this->render('task/success.stream.html.twig', ['task' => $task]);
18+
} else {
19+
$response = $this->render('task/success.html.twig', ['task' => $task]);
20+
}
21+
22+
return $response->setVary('Accept');
23+
}
24+
}
25+
```
26+
327
## 2.0
428

529
- Support for `stimulus` version 2 was removed and support for `@hotwired/stimulus`

src/Turbo/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ namespace App\Controller;
295295
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
296296
use Symfony\Component\HttpFoundation\Request;
297297
use Symfony\Component\HttpFoundation\Response;
298-
use Symfony\UX\Turbo\Stream\TurboStreamResponse;
298+
use Symfony\UX\Turbo\TurboBundle;
299299
use App\Entity\Task;
300300
301301
class TaskController extends AbstractController
@@ -311,9 +311,10 @@ class TaskController extends AbstractController
311311
// ... perform some action, such as saving the task to the database
312312
313313
// 🔥 The magic happens here! 🔥
314-
if (TurboStreamResponse::STREAM_FORMAT === $request->getPreferredFormat()) {
315-
// If the request comes from Turbo, only send the HTML to update using a TurboStreamResponse
316-
return $this->render('task/success.stream.html.twig', ['task' => $task], new TurboStreamResponse());
314+
if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
315+
// If the request comes from Turbo, set the content type as text/vnd.turbo-stream.html and only send the HTML to update
316+
$request->setFormat(TurboBundle::STREAM_FORMAT);
317+
return $this->render('task/success.stream.html.twig', ['task' => $task]);
317318
}
318319
319320
// If the client doesn't support JavaScript, or isn't using Turbo, the form still works as usual.

src/Turbo/Resources/config/services.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Symfony\UX\Turbo\Broadcaster\ImuxBroadcaster;
1717
use Symfony\UX\Turbo\Broadcaster\TwigBroadcaster;
1818
use Symfony\UX\Turbo\Doctrine\BroadcastListener;
19-
use Symfony\UX\Turbo\Stream\AddTurboStreamFormatSubscriber;
2019
use Symfony\UX\Turbo\Twig\TwigExtension;
2120

2221
/*
@@ -25,9 +24,6 @@
2524
return static function (ContainerConfigurator $container): void {
2625
$container->services()
2726

28-
->set('turbo.kernel.event_subscriber', AddTurboStreamFormatSubscriber::class)
29-
->tag('kernel.event_subscriber')
30-
3127
->set('turbo.broadcaster.imux', ImuxBroadcaster::class)
3228
->args([tagged_iterator('turbo.broadcaster')])
3329

src/Turbo/Stream/AddTurboStreamFormatSubscriber.php

Lines changed: 0 additions & 67 deletions
This file was deleted.

src/Turbo/Stream/TurboStreamResponse.php

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/Turbo/Tests/app/Kernel.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
use Symfony\Component\Mercure\HubInterface;
3535
use Symfony\Component\Mercure\Update;
3636
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
37-
use Symfony\UX\Turbo\Stream\TurboStreamResponse;
3837
use Symfony\UX\Turbo\TurboBundle;
3938
use Symfony\WebpackEncoreBundle\WebpackEncoreBundle;
4039
use Twig\Environment;
@@ -131,11 +130,14 @@ public function getProjectDir(): string
131130

132131
public function form(Request $request, Environment $twig): Response
133132
{
134-
if (TurboStreamResponse::STREAM_FORMAT === $request->getPreferredFormat()) {
135-
return new TurboStreamResponse($twig->render('form.stream.html.twig'));
133+
if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
134+
$request->setRequestFormat(TurboBundle::STREAM_FORMAT);
135+
$response = (new Response($twig->render('form.stream.html.twig')));
136+
} else {
137+
$response = new Response('Turbo not installed, default to plain HTML.');
136138
}
137139

138-
return new Response('Turbo not installed, default to plain HTML.');
140+
return $response->setVary('Accept');
139141
}
140142

141143
public function chat(Request $request, FormFactoryInterface $formFactory, HubInterface $mercureHub, Environment $twig): Response

src/Turbo/TurboBundle.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1515
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\HttpFoundation\Request;
1718
use Symfony\Component\HttpKernel\Bundle\Bundle;
1819

1920
/**
@@ -23,6 +24,14 @@
2324
*/
2425
final class TurboBundle extends Bundle
2526
{
27+
public const STREAM_FORMAT = 'turbo_stream';
28+
public const STREAM_MEDIA_TYPE = 'text/vnd.turbo-stream.html';
29+
30+
public function boot(): void
31+
{
32+
(new Request())->setFormat(self::STREAM_FORMAT, self::STREAM_MEDIA_TYPE);
33+
}
34+
2635
public function build(ContainerBuilder $container): void
2736
{
2837
parent::build($container);

0 commit comments

Comments
 (0)