Skip to content

Commit b3beab6

Browse files
committed
Added RouterContextMiddleware
1 parent d2e589c commit b3beab6

File tree

6 files changed

+227
-0
lines changed

6 files changed

+227
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Added the `dispatcher` option to `debug:event-dispatcher`
99
* Added the `event_dispatcher.dispatcher` tag
1010
* Added `assertResponseFormatSame()` in `BrowserKitAssertionsTrait`
11+
* Added the `RouterContextMiddleware` to restore the original router context when handling a message
1112

1213
5.2.0
1314
-----

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

+1
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,7 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
935935
if (!$this->isConfigEnabled($container, $config)) {
936936
$container->removeDefinition('console.command.router_debug');
937937
$container->removeDefinition('console.command.router_match');
938+
$container->removeDefinition('messenger.middleware.router_context');
938939

939940
return;
940941
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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\Bundle\FrameworkBundle\Messenger;
13+
14+
use Symfony\Component\Messenger\Envelope;
15+
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
16+
use Symfony\Component\Messenger\Middleware\StackInterface;
17+
use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp;
18+
use Symfony\Component\Routing\RequestContext;
19+
use Symfony\Component\Routing\RequestContextAwareInterface;
20+
21+
/**
22+
* Restore the Router context when processing the message.
23+
*
24+
* @author Jérémy Derussé <jeremy@derusse.com>
25+
*/
26+
class RouterContextMiddleware implements MiddlewareInterface
27+
{
28+
private $router;
29+
30+
public function __construct(RequestContextAwareInterface $router)
31+
{
32+
$this->router = $router;
33+
}
34+
35+
public function handle(Envelope $envelope, StackInterface $stack): Envelope
36+
{
37+
if (null !== $envelope->last(ConsumedByWorkerStamp::class)) {
38+
/** @var RouterContextStamp $contextStamp */
39+
if (null !== $contextStamp = $envelope->last(RouterContextStamp::class)) {
40+
$currentContext = $this->router->getContext();
41+
42+
$this->router->setContext(new RequestContext(
43+
$contextStamp->getBaseUrl(),
44+
$contextStamp->getMethod(),
45+
$contextStamp->getHost(),
46+
$contextStamp->getScheme(),
47+
$contextStamp->getHttpPort(),
48+
$contextStamp->getHttpsPort(),
49+
$contextStamp->getPathInfo(),
50+
$contextStamp->getQueryString()
51+
));
52+
53+
try {
54+
return $stack->next()->handle($envelope, $stack);
55+
} finally {
56+
$this->router->setContext($currentContext);
57+
}
58+
}
59+
} else {
60+
$context = $this->router->getContext();
61+
$envelope = $envelope->with(new RouterContextStamp(
62+
$context->getBaseUrl(),
63+
$context->getMethod(),
64+
$context->getHost(),
65+
$context->getScheme(),
66+
$context->getHttpPort(),
67+
$context->getHttpsPort(),
68+
$context->getPathInfo(),
69+
$context->getQueryString()
70+
));
71+
}
72+
73+
return $stack->next()->handle($envelope, $stack);
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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\Bundle\FrameworkBundle\Messenger;
13+
14+
use Symfony\Component\Messenger\Stamp\StampInterface;
15+
16+
/**
17+
* @author Jérémy Derussé <jeremy@derusse.com>
18+
*/
19+
class RouterContextStamp implements StampInterface
20+
{
21+
private $baseUrl;
22+
private $method;
23+
private $host;
24+
private $scheme;
25+
private $httpPort;
26+
private $httpsPort;
27+
private $pathInfo;
28+
private $queryString;
29+
30+
public function __construct(string $baseUrl, string $method, string $host, string $scheme, int $httpPort, int $httpsPort, string $pathInfo, string $queryString)
31+
{
32+
$this->baseUrl = $baseUrl;
33+
$this->method = $method;
34+
$this->host = $host;
35+
$this->scheme = $scheme;
36+
$this->httpPort = $httpPort;
37+
$this->httpsPort = $httpsPort;
38+
$this->pathInfo = $pathInfo;
39+
$this->queryString = $queryString;
40+
}
41+
42+
public function getBaseUrl(): string
43+
{
44+
return $this->baseUrl;
45+
}
46+
47+
public function getMethod(): string
48+
{
49+
return $this->method;
50+
}
51+
52+
public function getHost(): string
53+
{
54+
return $this->host;
55+
}
56+
57+
public function getScheme(): string
58+
{
59+
return $this->scheme;
60+
}
61+
62+
public function getHttpPort(): int
63+
{
64+
return $this->httpPort;
65+
}
66+
67+
public function getHttpsPort(): int
68+
{
69+
return $this->httpsPort;
70+
}
71+
72+
public function getPathInfo(): string
73+
{
74+
return $this->pathInfo;
75+
}
76+
77+
public function getQueryString(): string
78+
{
79+
return $this->queryString;
80+
}
81+
}

src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1313

14+
use Symfony\Bundle\FrameworkBundle\Messenger\RouterContextMiddleware;
1415
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory;
1516
use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory;
1617
use Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory;
@@ -100,6 +101,11 @@
100101
service('debug.stopwatch'),
101102
])
102103

104+
->set('messenger.middleware.router_context', RouterContextMiddleware::class)
105+
->args([
106+
service('router'),
107+
])
108+
103109
// Discovery
104110
->set('messenger.receiver_locator')
105111
->args([
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
4+
5+
use Symfony\Bundle\FrameworkBundle\Messenger\RouterContextMiddleware;
6+
use Symfony\Bundle\FrameworkBundle\Messenger\RouterContextStamp;
7+
use Symfony\Component\Messenger\Envelope;
8+
use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp;
9+
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
10+
use Symfony\Component\Routing\RequestContext;
11+
use Symfony\Component\Routing\RequestContextAwareInterface;
12+
13+
class RouterContextMiddlewareTest extends MiddlewareTestCase
14+
{
15+
public function testMiddlewareStoreContext()
16+
{
17+
$context = RequestContext::fromUri('https://symfony.com');
18+
19+
$router = $this->createMock(RequestContextAwareInterface::class);
20+
$router
21+
->expects($this->once())
22+
->method('getContext')
23+
->willReturn($context);
24+
25+
$middleware = new RouterContextMiddleware($router);
26+
27+
$envelope = new Envelope(new \stdClass());
28+
$envelope = $middleware->handle($envelope, $this->getStackMock());
29+
30+
$this->assertNotNull($stamp = $envelope->last(RouterContextStamp::class));
31+
$this->assertSame('symfony.com', $stamp->getHost());
32+
}
33+
34+
public function testMiddlewareRestoreContext()
35+
{
36+
$router = $this->createMock(RequestContextAwareInterface::class);
37+
$originalContext = new RequestContext();
38+
39+
$router
40+
->expects($this->once())
41+
->method('getContext')
42+
->willReturn($originalContext);
43+
44+
$router
45+
->expects($this->exactly(2))
46+
->method('setContext')
47+
->withConsecutive(
48+
[$this->callback(function ($context) {
49+
$this->assertSame('symfony.com', $context->getHost());
50+
51+
return true;
52+
})],
53+
[$originalContext]
54+
);
55+
56+
$middleware = new RouterContextMiddleware($router);
57+
$envelope = new Envelope(new \stdClass(), [
58+
new ConsumedByWorkerStamp(),
59+
new RouterContextStamp('', 'GET', 'symfony.com', 'https', 80, 443, '/', ''),
60+
]);
61+
$middleware->handle($envelope, $this->getStackMock());
62+
}
63+
}

0 commit comments

Comments
 (0)