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

[HttpFoundation] use InputBag for Request::$request only if data is coming from a form #37265

Merged
merged 1 commit into from Jun 15, 2020

Conversation

nicolas-grekas
Copy link
Member

Q A
Branch? 5.1
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #37100
License MIT
Doc PR -

@gmponos
Copy link
Contributor

gmponos commented Jun 13, 2020

Wont this make static analysis go crazy.. ???

@nicolas-grekas
Copy link
Member Author

@gmponos you made me realize I missed updating the @var annotation. Fixed.

@gmponos
Copy link
Contributor

gmponos commented Jun 14, 2020

Always positive :) at least something good came out from my comment.. check my comment on the related issue

Also I tried your changes locally at a project of mine and it seems that PHPStan is not complaining.

@fabpot
Copy link
Member

fabpot commented Jun 15, 2020

Thank you @nicolas-grekas.

@fabpot fabpot merged commit 05817f1 into symfony:5.1 Jun 15, 2020
@@ -298,7 +298,9 @@ public static function createFromGlobals()
{
$request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);

if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
if ($_POST) {
$request->request = new InputBag($_POST);
Copy link
Contributor

Choose a reason for hiding this comment

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

Most of the developers using symfony that will create a form using form component, let's say a login form, will get the data back as

`login` => [
    `username` => `user`,
    `password` =>  `password`,
];

So I don't see this InputBag here serving the majority..

Copy link
Member Author

Choose a reason for hiding this comment

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

The form component is already strict about strings vs arrays in values and knows how to deal with InputBag.

Copy link
Contributor

@gmponos gmponos Jun 15, 2020

Choose a reason for hiding this comment

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

Yes the form component, as a component knows how to deal with the InputBag.. my point is that users that will build a form with the component... they will never use this:

$request->request->get('login');

What use cases/bugs are you trying to cover by using for the request attribute the InputBag?

This means many apps just fail with a 500 when adding [] in the query string.

All this started with the scenario that someone access a query parameter and thinking that it is string etc etc.. ok.. although I disagree with the notion of it.. it is a UseCase. I don't see how developers will be protected by using InputBag on the request since most of the cases are submitting associative arrays...

All I see is that I have to do this:

        $login = $request->request->get('login');
        return \is_array($login) && isset($login['username']) && isset($login['password']) && isset($login['_token']);

to:

        $request = $request->request->all();
        if (!isset($request['login'])) {
            return false;
        }

        $login = $request['login'];
        return \is_array($login) && isset($login['username']) && isset($login['password']) && isset($login['_token']);

it's not the code that I have to write.. it's that ParameterBag::get is totally useless..

Hope I am explaining in the best way.. if not.. maybe we should move on.. there might be more important things to care..

Copy link
Member Author

Choose a reason for hiding this comment

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

Your "to" should be:

$request = $request->request->all('login');
return isset($login['username']) && isset($login['password']) && isset($login['_token']);

Then you'll let a BadRequestException bubble down and become a 400 as it should if you expect login to be an array. This "after" is much better than the "before" actually, with a richer behavior and more semantic code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then you'll let a BadRequestException bubble down and become a 400 as it should if you expect login to be an array.

I can't.. various technical reasons that are out of the topic of this discussion...

Still this remains:

it's not the code that I have to write.. it's that ParameterBag::get is totally useless..

}

return $value;
return parent::all($key);
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that you tried making the behavior between the two bags more similar.. nice.. not sure if you were driven by my comment... but this is indeed nice..

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't remember exactly my flow of thoughts, but it might be :)

@acasademont
Copy link
Contributor

Hi @nicolas-grekas , after merging #37327 should this be reverted? The InputBag|ParameterBag hint is making our phpstan analysis a bit useless due to the mixed return type of the ParameterBag::get() method. Now that null is allowed on InputBag this is not that relevant imho.

Not sure if I should open a PR, happy to do it, thx!

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Feb 26, 2021

I think using InputBag for accessing form payloads is the correct to provide type-safety at runtime.
The fact that static analyzers don't understand how this works should not be a reason to weaken the runtime checks.

@acasademont
Copy link
Contributor

acasademont commented Feb 26, 2021

Sure! What I mean is that InputBag could be used again for all types of requests, not only POST ones, no? With #37327 merged, the original bug #37100 is fixed too and then we can tighten the typehints again on the Request.

@nicolas-grekas
Copy link
Member Author

Possibly yes. InputBag is more restrictive than ParameterBag, but maybe that's still fine in practice even when the content is json. Feel free to give it a try :)

fabpot added a commit that referenced this pull request Mar 12, 2021
…sademont)

This PR was merged into the 5.3-dev branch.

Discussion
----------

[HttpFoundation] Use InputBag for POST requests too

| Q             | A
| ------------- | ---
| Branch?       | 5.x
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | Partially revert #37265
| License       | MIT
| Doc PR        | -

#37265 was created as a fix for #37100. However, when #37327 was merged, the original bug was also fixed with a different solution (allowing null values on `InputBag::set`) and parts of #37265 are not needed anymore. By using only `InputBag` as the `$request` bag we can tighten the typehint again and make static analysis a bit more useful.

Commits
-------

381a0a1 use InputBag for POST requests too, added missing scalar type hints
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.

None yet

5 participants