8000 [Form] allow additional http methods in form configuration by alekitto · Pull Request #26324 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Form] allow additional http methods in form configuration #26324

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

Merged
merged 1 commit into from
Oct 10, 2018

Conversation

alekitto
Copy link
Contributor
Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #26287
License MIT
Doc PR TBD

In order to allow HTTP methods other than GET, PUT, POST, DELETE and PATCH, the allowed_methods option under framework.form configuration has been added.
This configuration option adds the specified methods to the FormConfigBuilder whitelist, allowing that methods be used in form configuration via setMethod or the method option.

The use-case, that has been discussed in #26287, required the usage of custom HTTP method for describing a resource in an API application.

@vudaltsov
Copy link
Contributor

Can we just remove that in_array check? As far as I can see it's not influencing anything internally...
It could be a question of security but it should be solved not by forms but by server configuration.

@@ -70,6 +71,10 @@ public function boot()
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
Request::setTrustedHosts($trustedHosts);
}

if ($this->container->hasParameter('form.allowed_methods')) {
FormConfigBuilder::setAllowedMethods($this->container->getParameter('form.allowed_methods'));
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest to try harder not using any global state for this feature.
Could be just an option for FormConfigBuilder maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FormConfigBuilder is not instantiated by the DI container, but by the ResolvedFormType class which is created by ResolvedFormTypeFactory, so the injection of a parameter is too cumbersome. I tried to create a TypeExtension to inject the parameter as an option, but it can be overridden on any form type (this means that we can pass method and allowed methods as options and it I don't think it makes sense).

Now i tried to inject the allowed methods directly in the form factory which is set into the FormConfigBuilder. What do you think about this solution?

@alekitto alekitto force-pushed the master branch 3 times, most recently from 4b82548 to 4f5ab03 Compare March 19, 2018 23:35
@vudaltsov
Copy link
Contributor

What if if we move the check from setMethod() to $optionsResolver->setAllowedValues('method', [])?

This will give developers a possibility to write an extension for the FormType with $resolver->addAllowedValues('method', ['RESET']) and everyone will be happy :)

@nicolas-grekas nicolas-grekas modified the milestones: 4.1, next Apr 20, 2018
Copy link
Member
@xabbuh xabbuh left a comment

Choose a reason for hiding this comment

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

< 8000 !-- '"` -->

The solution suggested by @vudaltsov looks much better to me.

@alekitto alekitto force-pushed the master branch 4 times, most recently from 3e2a477 to 227da93 Compare August 28, 2018 13:35
@@ -29,7 +29,6 @@
<!-- FormFactory -->
<service id="form.factory" class="Symfony\Component\Form\FormFactory" public="true">
<argument type="service" id="form.registry" />
<argument type="service" id="form.resolved_type_factory" />
Copy link
Contributor

Choose a reason for hiding this comment

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

for 3.4?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The second constructor parameter was deleted in 3607eb3 (included in 3.3 beta 1).
Should I restore it?

Copy link
Member
@xabbuh xabbuh Sep 1, 2018

Choose a reason for hiding this comment

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

I think @ro0NL meant that this change could probably be made on a lower version of the FrameworkBundle too (i.e. all versions that do not support the Form component in version 3.2 or lower).

@vudaltsov
Copy link
Contributor

@alekitto , why don't you like my solution? Forms have a clear extension mechanism - that is OptionsResolver. Let's use it here!

@alekitto
Copy link
Contributor Author

@vudaltsov in fact i’ve used it in my last revision. I moved the allowedMethods const in FormType and used it to set the ‘method’ option allowed values

*
* @var array
*/
private static $allowedMethods = array(
Copy link
Contributor

Choose a reason for hiding this comment

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

private const?

@vudaltsov
Copy link
Contributor

@alekitto , I am so sorry, I missed that! Thank you :)

@@ -185,6 +203,11 @@ public function configureOptions(OptionsResolver $resolver)
$resolver->setAllowedTypes('label_attr', 'array');
$resolver->setAllowedTypes('upload_max_size_message', array('callable'));
$resolver->setAllowedTypes('help', array('string', 'null'));

$resolver->setAllowedValues('method', self::$allowedMethods);
Copy link
Member

Choose a reason for hiding this comment

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

You can work around with a closure function to avoid duplicated values ([lower|upper]case) in $allowedMethods:

$resolver->setAllowedValues('method', function ($value) {
    return \in_array($value, self::$allowedMethods);
});

@yceruto
Copy link
Member
yceruto commented Aug 30, 2018

My doubt at this point: setMethod() will accept any custom value but method option only the allowed by default, why not open this option too? (i.e. without allowed values) Otherwise, these paths are inconsistent (according to previous behavior).

@alekitto
Copy link
Contributor Author

@yceruto My first proposal on the issue was to remove the check entirely. You can find the reason for maintaining these checks in this comment

@yceruto
Copy link
Member
yceruto commented Aug 30, 2018

@alekitto Yes, I agree, but this proposal open setMethod() without restriction...and if we can do this now:

$this->createFormBuilder()->setMethod('RESET');

why can't I do this too (without add a type extension):

$this->createFormBuilder(null, ['method' => 'RESET']);

?

Note that the first alternative doesn't comply with the ref comment.

@alekitto
Copy link
Contributor Author

@yceruto You've got a point. I'm still thinking that the best option is to remove the checks and suggest to always use Request::METHOD_* constants to avoid misspelling. 

@yceruto
Copy link
Member
yceruto commented Aug 31, 2018

@alekitto I bet on that too 👍

@vudaltsov
Copy link
Contributor

So you suggest one check in setMethod() doing in_array($upperCasedMethod, [Request::METHOD_HEAD...])?

@yceruto
Copy link
Member
yceruto commented Aug 31, 2018

@vudaltsov I understood: remove the checks at all and documenting: **suggest** to always use Request::METHOD_* constants to avoid misspelling..

Is there any restriction to use a custom request method in HTTP world? if no: IMHO, it is not worth sacrificing this natural possibility in favor of the DX misspelling feature.

@xabbuh
Copy link
Member
xabbuh commented Sep 1, 2018

Technically the standard IIRC does not make any restriction on which HTTP methods you can use. There are some defined in the RFCs for which you are able to infer some semantics but that doesn't stop you from using your own methods. So maybe just removing the check here is the way to go.

@alekitto
Copy link
Contributor Author
alekitto commented Sep 1, 2018

@xabbuh Correct. The RFC 7231 defines some method names (GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE) and others have been registered in different RFCs, but does not restrict method names at all.
In fact, it simply defines method = token and then lists some standardized methods.

@xabbuh
Copy link
Member
xabbuh commented Oct 9, 2018

@alekitto Can you also add an entry to the component's changelog file?

@alekitto
Copy link
Contributor Author
alekitto commented Oct 9, 2018

@xabbuh Ok, done 👍

Copy link
Member
@fabpot fabpot left a comment

Choose a reason for hiding this comment

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

with a minor comment

@@ -9,6 +9,7 @@ CHANGELOG
* deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered
* added a cause when a CSRF error has occurred
* deprecated the `scale` option of the `IntegerType`
* removed restriction on allowed http methods
Copy link
Member

Choose a reason for hiding this comment

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

HTTP instead of http

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed

@xabbuh
Copy link
Member
xabbuh commented Oct 10, 2018

The build failure is not related, but requires a fix on how we run tests on Travis CI (#28788 or something like that).

@fabpot
Copy link
Member
fabpot commented Oct 10, 2018

Thank you @alekitto.

@fabpot fabpot merged commit 27d228c into symfony:master Oct 10, 2018
fabpot added a commit that referenced this pull request Oct 10, 2018
…tion (alekitto)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Form] allow additional http methods in form configuration

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #26287
| License       | MIT
| Doc PR        | TBD

In order to allow HTTP methods other than GET, PUT, POST, DELETE and PATCH, the `allowed_methods` option under `framework.form` configuration has been added.
This configuration option adds the specified methods to the `FormConfigBuilder` whitelist, allowing that methods be used in form configuration via `setMethod` or the `method` option.

The use-case, that has been discussed in #26287, required the usage of custom HTTP method for describing a resource in an API application.

Commits
-------

27d228c [Form] remove restriction on allowed http methods
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
This was referenced Nov 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants
0