-
-
Notifications
You must be signed in to change notification settings - Fork 838
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a flag to disable all request listeners #909
Add a flag to disable all request listeners #909
Conversation
@@ -45,13 +45,17 @@ public function __construct(ValidatorInterface $validator, ResourceMetadataFacto | |||
public function onKernelView(GetResponseForControllerResultEvent $event) | |||
{ | |||
$request = $event->getRequest(); | |||
if ($request->isMethodSafe(false) || $request->isMethod(Request::METHOD_DELETE)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change isn't really related, but is a minor performance improvement.
Actually, in my context, I did not want to remove all listeners. juste the deserialization. I guess you will understand better my use case will "real code" /**
* @Route(
* name="api_envs_add_member",
* path="/api/v2/envs/{env}/members",
* )
* @Method("POST")
* @Security("is_granted('CONFIGURE', env)")
*/
public function addMemberAction(Request $request, AbstractEnv $env)
{
$envMember = new EnvMember($this->getUser(), $env);
$form = $this->container->get('form.factory')
->createNamed('', EnvMemberType::class, $envMember)
->handleRequest($request)
;
$violations = $this->get('validator')->validate($envMember);
if (0 !== count($violations)) {
// use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException;
throw new ValidationException($violations);
}
$this->get('profiler.server_sharing')->approve($this->getUser(), $env, $envMember->getEmail());
// Fake until https://github.com/api-platform/core/issues/880 is fixed
$request->attributes->set('_api_resource_class', AbstractEnv::class);
$request->attributes->set('_api_item_operation_name', 'add member');
return $env;
} |
It removes only "request listeners" (write listeners), so it will do the trick (the serialization process will still work). |
Unrelated but: // Fake until https://github.com/api-platform/core/issues/880 is fixed
$request->attributes->set('_api_resource_class', AbstractEnv::class);
$request->attributes->set('_api_item_operation_name', 'add member'); It works when attributes are set manually but not when the router sets them? Weird. |
Actually it's a big HACK
so in practice curl -X POST /../env-id/members -d "{email="xxx", ...}" |
Got it, sorry about that. This PR should fix your issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have some time to add that 0.05% of coverage , coveralls will be happy :).
if (null === $apiRequest = $request->attributes->get('_api_request')) { | ||
$result['request'] = true; | ||
} else { | ||
$result['request'] = (bool) $apiRequest; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What could be the value of this ? true / false or just false ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true / false, 1 / 0 (when using a route to define the attribute).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this cast. It lets through more than what we want to support. We should use an explicit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes me too but the cast is mandatory to support the routing component < 3.2 (before this version, types wasn't supported and the user was able to put anything that can be casted to a boolean in such cases).
I'm -1 because one could just create custom routes and controllers / actions outside of the API Platform system altogether. This is an unwelcome hack. |
It doesn't sound like a hack to me. What do you suggest to fix the issue raised by @lyrixx? |
ping @teohhanhui, I would like to merge this asap. |
I'm still -1. If we proceed with this, sooner or later we'll be adding This is a misfeature. If we want to allow for more flexibility, we should add extension points (if they are not already available) and/or the possibility to decorate the listeners. For example, I'm able to do what was requested in #781 by decorating the DeserializeListener. I suspect #880 can use a similar solution. |
@teohhanhui wanting to deal with the request "manually" without any preprocessing done by the framework is a very common use case and one of the most wanted feature (see the list of referenced tickets). Indeed it can already be done using extension points, but having to decorate services to do a so common operation is too much work for the developper IMO.
It's not gonna to happen. The point here is to skip entirely the preprocessing. |
Uhh, okay. I didn't notice there's |
if (null === $apiRequest = $request->attributes->get('_api_request')) { | ||
$result['request'] = true; | ||
} else { | ||
$result['request'] = (bool) $apiRequest; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this cast. It lets through more than what we want to support. We should use an explicit test.
@@ -61,6 +61,24 @@ public function testDoNotCallWhenRequestNotManaged() | |||
$listener->onKernelRequest($eventProphecy->reveal()); | |||
} | |||
|
|||
public function testDoNotCallWhenRequestRequestIsFalse() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps testDoNotCallWhenRequestSkipRequestProcessing
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testDoNotCallWhenRequestSkipProcessing
seems more accurate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's only request processing that's being skipped, not all processing. In a similar fashion we could say "skip response processing".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking more about it, we have api_respond
, not api_response
. So maybe it should be api_receive
? @dunglas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the corresponding term would be "skip receive"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api_receive
Love it. I'll update the PR.
@@ -39,6 +39,24 @@ public function testNotAnApiPlatformRequest() | |||
$listener->onKernelRequest($event->reveal()); | |||
} | |||
|
|||
public function testRequestIsFalse() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should try to standardize the test function names (like above)...
f13c4c4
to
013ae68
Compare
Attribute renamed |
To disable all API Platform request listeners (read, deserialize and validate), you have to create a new request attribute (for instance by setting the
defaults
key in a route definition) calledapi_request
to false.ping @lyrixx, @kbsali, @gpenverne.