Skip to content
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

Authorize empty content put in custom operations #1274

Merged

Conversation

thomasglachant
Copy link
Contributor

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets no
License MIT
Doc PR NA

This PR allows to send empty request content for PUT in a custom operation.

Use case :
I have a custom Action (ex : "reset") associated to an ApiResource "Job".
I don't have any request content to send when I send a PUT request to /jobs/1234/reset.
But I've a SerializerError because the request content is required.

@thomasglachant thomasglachant force-pushed the authorize-empty-content-put branch from a2ccd4f to 84fd4a6 Compare July 21, 2017 13:13
@@ -51,6 +51,7 @@ public function onKernelRequest(GetResponseEvent $event)
|| $request->isMethod(Request::METHOD_DELETE)
|| !($attributes = RequestAttributesExtractor::extractAttributes($request))
|| !$attributes['receive']
|| ($request->isMethod(Request::METHOD_PUT) && $request->getContent() === '')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you store the result of $request->getContent() in a variable to avoid 2 (costly) method calls (the next one is line 70)?
Also, please use Yoda styl ('' === $content).

@@ -52,7 +52,7 @@ public function onKernelRequest(GetResponseEvent $event)
|| $request->isMethod(Request::METHOD_DELETE)
|| !($attributes = RequestAttributesExtractor::extractAttributes($request))
|| !$attributes['receive']
|| ($request->isMethod(Request::METHOD_PUT) && '' === $requestContent)
|| ($request->isMethod(Request::METHOD_PUT) && '' === $requestContent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I suggest:

|| ($request->isMethod(Request::METHOD_PUT) && '' === ($requestContent = $request->getContent()))

It will avoid to always retrieve the body (that can be huge) in most cases.

Copy link
Contributor Author

@thomasglachant thomasglachant Jul 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I can do it, but it's a little more complicated because it's a "&&" and for a POST we don't initialize the variable.
So I need to add $requestContent ?? $request->getContent() in the deserialize line.

It will be faster but less clear.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this listener will be executed for every request (even if its a page not managed by API Platform), let's use the fastest alternative.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done ! I add a behat test with the empty body ... don't know if it's necessary ...

@meyerbaptiste
Copy link
Member

in custom operation

But in reality it will work for all PUT operations, custom or not. Do we really want this?

@dunglas
Copy link
Member

dunglas commented Jul 21, 2017

What's the behavior with this patch when an empty request is sent to a standard PUT route?

@meyerbaptiste
Copy link
Member

We have a 200 with the unmodified resource instead of a 400.

@thomasglachant
Copy link
Contributor Author

What's the behavior with this patch when an empty request is sent to a standard PUT route?

Nothing (200) ... I wrote a behat test to check. It's like a PUT request with an empty array in body.

@dunglas
Copy link
Member

dunglas commented Jul 21, 2017

It looks acceptable to me. WDYT @api-platform/core-team?

@soyuka
Copy link
Member

soyuka commented Jul 21, 2017

Ok to me.

@meyerbaptiste
Copy link
Member

meyerbaptiste commented Jul 21, 2017

It looks like a BC break to have a 200 instead of a 400 now (for a standard PUT). Nop?

@soyuka
Copy link
Member

soyuka commented Jul 21, 2017

Lot of overhead if we need to check that it's a custom operation no?

@dunglas
Copy link
Member

dunglas commented Jul 21, 2017

It's borderline, but it looks acceptable. Who would rely on an empty request throwing a 400?

if (
$request->isMethodSafe(false)
|| $request->isMethod(Request::METHOD_DELETE)
|| !($attributes = RequestAttributesExtractor::extractAttributes($request))
|| !$attributes['receive']
|| ($request->isMethod(Request::METHOD_PUT) && '' === ($requestContent = $request->getContent()))
Copy link
Member

@dunglas dunglas Jul 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you invert the conditions (('' === $requestContent = $request->getContent()) && $request->isMethod(Request::METHOD_PUT)), you don't need the trick with ?? anymore because the variable will always be defined. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, clean and fast 👍

@thomasglachant thomasglachant force-pushed the authorize-empty-content-put branch from 208695c to b55eb08 Compare July 22, 2017 08:29
@@ -395,6 +395,41 @@ Feature: Create-Retrieve-Update-Delete
}
"""

Scenario: Update a resource with empty body
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dunglas Do you think it's necessary to add this test ? I'm not convinced ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no useless integration test ;).

@Simperfit
Copy link
Contributor

It's not like someone should rely on a 400 return. LGTM

Copy link
Member

@meyerbaptiste meyerbaptiste left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@soyuka soyuka merged commit a3b62e8 into api-platform:master Jul 24, 2017
@soyuka
Copy link
Member

soyuka commented Jul 24, 2017

Thanks @thomasglachant !

@thomasglachant thomasglachant deleted the authorize-empty-content-put branch July 24, 2017 08:55
@teohhanhui
Copy link
Contributor

teohhanhui commented Jul 24, 2017

-1

I really do not understand why this needs to be specially handled. What happened to the PR(s) on allowing empty request body?

@soyuka
Copy link
Member

soyuka commented Jul 24, 2017

Empty request body does make sense only with PUT / DELETE requests no?

@teohhanhui
Copy link
Contributor

No. See #782 and #805.

hoangnd25 pushed a commit to hoangnd25/core that referenced this pull request Feb 23, 2018
* Authorize empty request content for PUT in a custom action

* Apply php-cs-fixer

* Apply review changes

* Apply review changes

* Switch to fastest alternative. Add behat test for with empty body on PUT.

* Refacto after dunglas review
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants