Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit81db2d4

Browse files
committed
featuresymfony#89 PSR HTTP message converters for controllers (derrabus)
This PR was merged into the 2.0-dev branch.Discussion----------PSR HTTP message converters for controllersThis PR proposes to add two classes to `symfony/psr-http-message-bridge` that have been removed from `sensio/framework-extra-bundle`.By adding `PsrServerRequestResolver` and `PsrResponseListener` to its service container, with autowring and autoconfiguring enabled, an application gains the ability to operate controllers on PSR-7 message objects instead of HttpFoundation.This is especially useful if a developer wants to reuse generic packages like `league/oauth2-server`.Configuration files for autowiring the two classes can be provided as Flex recipes.Commits-------aa26e61 PSR HTTP message converters for controllers
2 parentse62b239 +aa26e61 commit81db2d4

File tree

11 files changed

+450
-2
lines changed

11 files changed

+450
-2
lines changed

‎.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ composer.lock
33
phpunit.xml
44
.php_cs.cache
55
.phpunit.result.cache
6+
/Tests/Fixtures/App/var
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespaceSymfony\Bridge\PsrHttpMessage\ArgumentValueResolver;
4+
5+
usePsr\Http\Message\MessageInterface;
6+
usePsr\Http\Message\RequestInterface;
7+
usePsr\Http\Message\ServerRequestInterface;
8+
useSymfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
9+
useSymfony\Component\HttpFoundation\Request;
10+
useSymfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
11+
useSymfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
12+
13+
/**
14+
* Injects the RequestInterface, MessageInterface or ServerRequestInterface when requested.
15+
*
16+
* @author Iltar van der Berg <kjarli@gmail.com>
17+
* @author Alexander M. Turek <me@derrabus.de>
18+
*/
19+
finalclass PsrServerRequestResolverimplements ArgumentValueResolverInterface
20+
{
21+
privateconstSUPPORTED_TYPES = [
22+
ServerRequestInterface::class =>true,
23+
RequestInterface::class =>true,
24+
MessageInterface::class =>true,
25+
];
26+
27+
private$httpMessageFactory;
28+
29+
publicfunction__construct(HttpMessageFactoryInterface$httpMessageFactory)
30+
{
31+
$this->httpMessageFactory =$httpMessageFactory;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
publicfunctionsupports(Request$request,ArgumentMetadata$argument):bool
38+
{
39+
returnself::SUPPORTED_TYPES[$argument->getType()] ??false;
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
publicfunctionresolve(Request$request,ArgumentMetadata$argument):\Traversable
46+
{
47+
yield$this->httpMessageFactory->createRequest($request);
48+
}
49+
}

‎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+
#2.1.0 (2021-02-17)
5+
6+
* Added a`PsrResponseListener` to automatically convert PSR-7 responses returned by controllers
7+
* Added a`PsrServerRequestResolver` that allows injecting PSR-7 request objects into controllers
8+
49
#2.0.2 (2020-09-29)
510

611
* Fix populating server params from URI in HttpFoundationFactory

‎EventListener/PsrResponseListener.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespaceSymfony\Bridge\PsrHttpMessage\EventListener;
4+
5+
usePsr\Http\Message\ResponseInterface;
6+
useSymfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
7+
useSymfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
8+
useSymfony\Component\EventDispatcher\EventSubscriberInterface;
9+
useSymfony\Component\HttpKernel\Event\ViewEvent;
10+
useSymfony\Component\HttpKernel\KernelEvents;
11+
12+
/**
13+
* Converts PSR-7 Response to HttpFoundation Response using the bridge.
14+
*
15+
* @author Kévin Dunglas <dunglas@gmail.com>
16+
* @author Alexander M. Turek <me@derrabus.de>
17+
*/
18+
finalclass PsrResponseListenerimplements EventSubscriberInterface
19+
{
20+
private$httpFoundationFactory;
21+
22+
publicfunction__construct(HttpFoundationFactoryInterface$httpFoundationFactory =null)
23+
{
24+
$this->httpFoundationFactory =$httpFoundationFactory ??newHttpFoundationFactory();
25+
}
26+
27+
/**
28+
* Do the conversion if applicable and update the response of the event.
29+
*/
30+
publicfunctiononKernelView(ViewEvent$event):void
31+
{
32+
$controllerResult =$event->getControllerResult();
33+
34+
if (!$controllerResultinstanceof ResponseInterface) {
35+
return;
36+
}
37+
38+
$event->setResponse($this->httpFoundationFactory->createResponse($controllerResult));
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
publicstaticfunctiongetSubscribedEvents():array
45+
{
46+
return [
47+
KernelEvents::VIEW =>'onKernelView',
48+
];
49+
}
50+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespaceSymfony\Bridge\PsrHttpMessage\Tests\ArgumentValueResolver;
4+
5+
usePHPUnit\Framework\TestCase;
6+
usePsr\Http\Message\MessageInterface;
7+
usePsr\Http\Message\RequestInterface;
8+
usePsr\Http\Message\ServerRequestInterface;
9+
useSymfony\Bridge\PsrHttpMessage\ArgumentValueResolver\PsrServerRequestResolver;
10+
useSymfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
11+
useSymfony\Component\HttpFoundation\Request;
12+
useSymfony\Component\HttpKernel\Controller\ArgumentResolver;
13+
14+
/**
15+
* @author Alexander M. Turek <me@derrabus.de>
16+
*/
17+
finalclass PsrServerRequestResolverTestextends TestCase
18+
{
19+
publicfunctiontestServerRequest()
20+
{
21+
$symfonyRequest =$this->createMock(Request::class);
22+
$psrRequest =$this->createMock(ServerRequestInterface::class);
23+
24+
$resolver =$this->bootstrapResolver($symfonyRequest,$psrRequest);
25+
26+
self::assertSame([$psrRequest],$resolver->getArguments($symfonyRequest,staticfunction (ServerRequestInterface$serverRequest):void {}));
27+
}
28+
29+
publicfunctiontestRequest()
30+
{
31+
$symfonyRequest =$this->createMock(Request::class);
32+
$psrRequest =$this->createMock(ServerRequestInterface::class);
33+
34+
$resolver =$this->bootstrapResolver($symfonyRequest,$psrRequest);
35+
36+
self::assertSame([$psrRequest],$resolver->getArguments($symfonyRequest,staticfunction (RequestInterface$request):void {}));
37+
}
38+
39+
publicfunctiontestMessage()
40+
{
41+
$symfonyRequest =$this->createMock(Request::class);
42+
$psrRequest =$this->createMock(ServerRequestInterface::class);
43+
44+
$resolver =$this->bootstrapResolver($symfonyRequest,$psrRequest);
45+
46+
self::assertSame([$psrRequest],$resolver->getArguments($symfonyRequest,staticfunction (MessageInterface$request):void {}));
47+
}
48+
49+
privatefunctionbootstrapResolver(Request$symfonyRequest,ServerRequestInterface$psrRequest):ArgumentResolver
50+
{
51+
$messageFactory =$this->createMock(HttpMessageFactoryInterface::class);
52+
$messageFactory->expects(self::once())
53+
->method('createRequest')
54+
->with(self::identicalTo($symfonyRequest))
55+
->willReturn($psrRequest);
56+
57+
returnnewArgumentResolver(null, [newPsrServerRequestResolver($messageFactory)]);
58+
}
59+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespaceSymfony\Bridge\PsrHttpMessage\Tests\EventListener;
4+
5+
usePHPUnit\Framework\TestCase;
6+
useSymfony\Bridge\PsrHttpMessage\EventListener\PsrResponseListener;
7+
useSymfony\Bridge\PsrHttpMessage\Tests\Fixtures\Response;
8+
useSymfony\Component\HttpFoundation\Request;
9+
useSymfony\Component\HttpKernel\Event\ViewEvent;
10+
useSymfony\Component\HttpKernel\HttpKernelInterface;
11+
12+
/**
13+
* @author Kévin Dunglas <dunglas@gmail.com>
14+
*/
15+
class PsrResponseListenerTestextends TestCase
16+
{
17+
publicfunctiontestConvertsControllerResult()
18+
{
19+
$listener =newPsrResponseListener();
20+
$event =$this->createEventMock(newResponse());
21+
$listener->onKernelView($event);
22+
23+
self::assertTrue($event->hasResponse());
24+
}
25+
26+
publicfunctiontestDoesNotConvertControllerResult()
27+
{
28+
$listener =newPsrResponseListener();
29+
$event =$this->createEventMock([]);
30+
31+
$listener->onKernelView($event);
32+
self::assertFalse($event->hasResponse());
33+
34+
$event =$this->createEventMock(null);
35+
36+
$listener->onKernelView($event);
37+
self::assertFalse($event->hasResponse());
38+
}
39+
40+
privatefunctioncreateEventMock($controllerResult):ViewEvent
41+
{
42+
returnnewViewEvent($this->createMock(HttpKernelInterface::class),newRequest(), HttpKernelInterface::MASTER_REQUEST,$controllerResult);
43+
}
44+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespaceSymfony\Bridge\PsrHttpMessage\Tests\Fixtures\App\Controller;
4+
5+
usePsr\Http\Message\MessageInterface;
6+
usePsr\Http\Message\RequestInterface;
7+
usePsr\Http\Message\ResponseFactoryInterface;
8+
usePsr\Http\Message\ResponseInterface;
9+
usePsr\Http\Message\ServerRequestInterface;
10+
usePsr\Http\Message\StreamFactoryInterface;
11+
12+
finalclass PsrRequestController
13+
{
14+
private$responseFactory;
15+
private$streamFactory;
16+
17+
publicfunction__construct(ResponseFactoryInterface$responseFactory,StreamFactoryInterface$streamFactory)
18+
{
19+
$this->responseFactory =$responseFactory;
20+
$this->streamFactory =$streamFactory;
21+
}
22+
23+
publicfunctionserverRequestAction(ServerRequestInterface$request):ResponseInterface
24+
{
25+
return$this->responseFactory
26+
->createResponse()
27+
->withBody($this->streamFactory->createStream(sprintf('<html><body>%s</body></html>',$request->getMethod())));
28+
}
29+
30+
publicfunctionrequestAction(RequestInterface$request):ResponseInterface
31+
{
32+
return$this->responseFactory
33+
->createResponse()
34+
->withStatus(403)
35+
->withBody($this->streamFactory->createStream(sprintf('<html><body>%s %s</body></html>',$request->getMethod(),$request->getBody()->getContents())));
36+
}
37+
38+
publicfunctionmessageAction(MessageInterface$request):ResponseInterface
39+
{
40+
return$this->responseFactory
41+
->createResponse()
42+
->withStatus(422)
43+
->withBody($this->streamFactory->createStream(sprintf('<html><body>%s</body></html>',$request->getHeader('X-My-Header')[0])));
44+
}
45+
}

‎Tests/Fixtures/App/Kernel.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespaceSymfony\Bridge\PsrHttpMessage\Tests\Fixtures\App;
4+
5+
useNyholm\Psr7\Factory\Psr17Factory;
6+
usePsr\Http\Message\ResponseFactoryInterface;
7+
usePsr\Http\Message\ServerRequestFactoryInterface;
8+
usePsr\Http\Message\StreamFactoryInterface;
9+
usePsr\Http\Message\UploadedFileFactoryInterface;
10+
usePsr\Log\NullLogger;
11+
useSymfony\Bridge\PsrHttpMessage\ArgumentValueResolver\PsrServerRequestResolver;
12+
useSymfony\Bridge\PsrHttpMessage\EventListener\PsrResponseListener;
13+
useSymfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
14+
useSymfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
15+
useSymfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
16+
useSymfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
17+
useSymfony\Bridge\PsrHttpMessage\Tests\Fixtures\App\Controller\PsrRequestController;
18+
useSymfony\Bundle\FrameworkBundle\FrameworkBundle;
19+
useSymfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
20+
useSymfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
21+
useSymfony\Component\HttpKernel\KernelasSymfonyKernel;
22+
useSymfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
23+
24+
class Kernelextends SymfonyKernel
25+
{
26+
use MicroKernelTrait;
27+
28+
publicfunctionregisterBundles():iterable
29+
{
30+
yieldnewFrameworkBundle();
31+
}
32+
33+
publicfunctiongetProjectDir():string
34+
{
35+
return__DIR__;
36+
}
37+
38+
protectedfunctionconfigureRoutes(RoutingConfigurator$routes):void
39+
{
40+
$routes
41+
->add('server_request','/server-request')->controller([PsrRequestController::class,'serverRequestAction'])->methods(['GET'])
42+
->add('request','/request')->controller([PsrRequestController::class,'requestAction'])->methods(['POST'])
43+
->add('message','/message')->controller([PsrRequestController::class,'messageAction'])->methods(['PUT'])
44+
;
45+
}
46+
47+
protectedfunctionconfigureContainer(ContainerConfigurator$container):void
48+
{
49+
$container->extension('framework', [
50+
'router' => ['utf8' =>true],
51+
'secret' =>'for your eyes only',
52+
'test' =>true,
53+
]);
54+
55+
$container->services()
56+
->set('nyholm.psr_factory', Psr17Factory::class)
57+
->alias(ResponseFactoryInterface::class,'nyholm.psr_factory')
58+
->alias(ServerRequestFactoryInterface::class,'nyholm.psr_factory')
59+
->alias(StreamFactoryInterface::class,'nyholm.psr_factory')
60+
->alias(UploadedFileFactoryInterface::class,'nyholm.psr_factory')
61+
;
62+
63+
$container->services()
64+
->defaults()->autowire()->autoconfigure()
65+
->set(HttpFoundationFactoryInterface::class, HttpFoundationFactory::class)
66+
->set(HttpMessageFactoryInterface::class, PsrHttpFactory::class)
67+
->set(PsrResponseListener::class)
68+
->set(PsrServerRequestResolver::class)
69+
;
70+
71+
$container->services()
72+
->set('logger', NullLogger::class)
73+
->set(PsrRequestController::class)->public()->autowire()
74+
;
75+
}
76+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp