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

Appearance settings

Commit 30810f6

Browse filesBrowse files
committed
[HttpKernel] Enhance MapRequestPayload adding format and validation group
1 parent f842797 commit 30810f6
Copy full SHA for 30810f6

File tree

Expand file treeCollapse file tree

3 files changed

+25
-9
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+25
-9
lines changed

‎src/Symfony/Component/HttpKernel/Attribute/MapRequestPayload.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Attribute/MapRequestPayload.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\HttpKernel\Attribute;
1313

1414
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver;
15+
use Symfony\Component\Validator\Constraints\GroupSequence;
1516

1617
/**
1718
* Controller parameter tag to map the request content to typed object and validate it.
@@ -22,7 +23,9 @@
2223
class MapRequestPayload extends ValueResolver
2324
{
2425
public function __construct(
26+
public readonly array|string|null $format = null,
2527
public readonly array $context = [],
28+
public readonly string|GroupSequence|array|null|false $groups = null,
2629
string $resolver = RequestPayloadValueResolver::class,
2730
) {
2831
parent::__construct($resolver);

‎src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php
+14-9Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
6969
continue;
7070
}
7171

72-
if (!$type = $argument->getType()) {
72+
if (!$argument->getType()) {
7373
throw new \LogicException(sprintf('Could not resolve the "$%s" controller argument: argument should be typed.', $argument->getName()));
7474
}
7575

7676
if ($this->validator) {
7777
$violations = new ConstraintViolationList();
7878
try {
79-
$payload = $this->$payloadMapper($request, $type, $attributes[0]);
79+
$payload = $this->$payloadMapper($request, $argument, $attributes[0]);
8080
} catch (PartialDenormalizationException $e) {
8181
$trans = $this->translator ? $this->translator->trans(...) : fn ($m, $p) => strtr($m, $p);
8282
foreach ($e->getErrors() as $error) {
@@ -92,15 +92,15 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
9292
}
9393

9494
if (null !== $payload) {
95-
$violations->addAll($this->validator->validate($payload));
95+
$violations->addAll($this->validator->validate($payload, null, $attributes[0]->groups ?? null));
9696
}
9797

9898
if (\count($violations)) {
9999
throw new HttpException($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), iterator_to_array($violations))), new ValidationFailedException($payload, $violations));
100100
}
101101
} else {
102102
try {
103-
$payload = $this->$payloadMapper($request, $type, $attributes[0]);
103+
$payload = $this->$payloadMapper($request, $argument, $attributes[0]);
104104
} catch (PartialDenormalizationException $e) {
105105
throw new HttpException($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), $e->getErrors())), $e);
106106
}
@@ -114,19 +114,19 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
114114
return [];
115115
}
116116

117-
private function mapQueryString(Request $request, string $type, MapQueryString $attribute): ?object
117+
private function mapQueryString(Request $request, ArgumentMetadata $argument, MapQueryString $attribute): ?object
118118
{
119119
if (!$data = $request->query->all()) {
120120
return null;
121121
}
122122

123-
return $this->serializer->denormalize($data, $type, null, self::CONTEXT_DENORMALIZE + $attribute->context);
123+
return $this->serializer->denormalize($data, $argument->getType(), null, self::CONTEXT_DENORMALIZE + $attribute->context);
124124
}
125125

126-
private function mapRequestPayload(Request $request, string $type, MapRequestPayload $attribute): ?object
126+
private function mapRequestPayload(Request $request, ArgumentMetadata $argument, MapRequestPayload $attribute): ?object
127127
{
128128
if ($data = $request->request->all()) {
129-
return $this->serializer->denormalize($data, $type, null, self::CONTEXT_DENORMALIZE + $attribute->context);
129+
return $this->serializer->denormalize($data, $argument->getType(), null, self::CONTEXT_DENORMALIZE + $attribute->context);
130130
}
131131

132132
if ('' === $data = $request->getContent()) {
@@ -137,12 +137,17 @@ private function mapRequestPayload(Request $request, string $type, MapRequestPay
137137
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, 'Unsupported format.');
138138
}
139139

140+
$acceptedFormats = is_string($attribute->format) ? [$attribute->format] : $attribute->format;
141+
if (is_array($attribute->format) && !in_array($format, $acceptedFormats, true)) {
142+
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, sprintf('Unsupported format, expects "%s", but "%s" given.', implode('", "', $acceptedFormats), $format));
143+
}
144+
140145
if ('form' === $format) {
141146
throw new HttpException(Response::HTTP_BAD_REQUEST, 'Request payload contains invalid "form" data.');
142147
}
143148

144149
try {
145-
return $this->serializer->deserialize($data, $type, $format, self::CONTEXT_DESERIALIZE + $attribute->context);
150+
return $this->serializer->deserialize($data, $argument->getType(), $format, self::CONTEXT_DESERIALIZE + $attribute->context);
146151
} catch (UnsupportedFormatException $e) {
147152
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, sprintf('Unsupported format: "%s".', $format), $e);
148153
} catch (NotEncodableValueException $e) {

‎src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestPayloadValueResolverTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestPayloadValueResolverTest.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ public function testRequestInputValidationPassed()
181181

182182
$this->assertEquals($payload, $resolver->resolve($request, $argument)[0]);
183183
}
184+
185+
public function testNonSupportedRestrictedFormatMustThrowUnsupportedMediaTypeException()
186+
{
187+
}
188+
189+
public function testRestrictGroupValidation()
190+
{
191+
}
184192
}
185193

186194
class RequestPayload

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.