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

Add support for parsing query string in QueryParameters #10521

Merged
merged 9 commits into from
Apr 6, 2021

Conversation

Artur-
Copy link
Member

@Artur- Artur- commented Mar 31, 2021

This is a prerequisite for #10431 split out to a separate PR for easier review

private static Map<String, List<String>> parseQueryString(
String queryString) {
List<NameValuePair> params = URLEncodedUtils.parse(queryString,
StandardCharsets.UTF_8);
Copy link
Contributor

@pleku pleku Apr 1, 2021

Choose a reason for hiding this comment

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

The only place where apache.http.client is used is in devmode for downloading node - that has been copied from frontend-maven-plugin. And that code should be removed from flow-server to its own place so that would not be leaking to user applications. But this is not your fault.

But if you introduce a further dependency to it, then it will be more difficult for us to make this refactoring.
This code is not the same exactly, but close to what Location does too to query parameters. Would it be possible to reuse-modify the code there instead ?

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 will move the code from Location.parseParams to replace this. Would have helped a lot if it had been in the correct class earlier.

Sadly the implementation is partly broken so it also needs to be fixed at the same time

Copy link
Member Author

Choose a reason for hiding this comment

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

Overall I don't understand why we have this generic util methods implemented in the framework in a slightly broken way when there are perfectly fine and tested util libraries out there that you can use.

The current method needed two fixes to be compatible with what HttpServletRequest.getParameters returns:

  1. It needs to decode values
  2. A parameter like "?hello" should map to an empty string and not no value at all like the old method did

Hopefully this does not break something else then

Copy link
Contributor

Choose a reason for hiding this comment

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

Overall I don't understand why we have this generic util methods implemented in the framework in a slightly broken way when there are perfectly fine and tested util libraries out there that you can use

The problem is the broken code in the code base. We should not try reinvent the wheel, but also not bring in libraries only to depend on a subset of the code there. It is a balancing act.

Copy link
Member Author

Choose a reason for hiding this comment

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

If you want to avoid external dependencies, there is always the possibility of rebasing the given class and including it directly in the project. Then it is possible to update it etc for new releases, there are no conflicts and no dependencies either

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes I think that is the least bad solution, to copy-paste the code and update it manually, in case the code cannot be / is not released as a standalone module.

Copy link
Member Author

Choose a reason for hiding this comment

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

So should we do it here? In that case I would revert to the original version more or less to use the lib and then make a separate PR about including it directly in the project instead of as a dependency

Copy link
Member Author

Choose a reason for hiding this comment

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

Because of the internal dependencies, it might not make sense to copy paste... It would lead to extracting the whole httpcore jar into the project

Copy link
Contributor

@pleku pleku left a comment

Choose a reason for hiding this comment

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

(just changing status to show that this is not waiting for review)

Copy link
Contributor

@pleku pleku left a comment

Choose a reason for hiding this comment

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

One question and suggestion (for the code in another comment).

--

The changes in this PR are fine, but when I look at the code flow (which this PR doesn't change, just the implementation), it does smell a bit. It seems like the code in the framework could be (later) improved to

  1. only parse the query parameters when needed
  2. cache the query strings for the ongoing request, now parse again and again
  3. see if the query string parsing code from the http request implementation could be reused, like from AtmosphereRequest since it handles both 1+2 from above
    I can create an issue for this after this is merged.

@@ -97,6 +99,66 @@ public static QueryParameters simple(Map<String, String> parameters) {
entry -> Collections.singletonList(entry.getValue())));
}

/**
* Creates parameters from a query string.
*
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the code is fine. But as the string can come from the user, this parsing might be a subject for DoS exploit, but I think the computations done inside the stream-map-collect are so simple that the query string limit of 1024 characters should not make it exploitable. Do you agree ?

I would consider adding some clarification to the method javadocs that this is code here is not checking for the length of the given query string - it is the responsibility of the caller.

Copy link
Member Author

Choose a reason for hiding this comment

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

Where would the DoS exploit possibility come from?

Copy link
Contributor

Choose a reason for hiding this comment

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

Like discussed separately, from using this code to parse a string that originates from client and it is very very long and because it is for some reason limited to 1024. This comment is enough for now.

@vaadin-bot vaadin-bot added +1.0.0 and removed +0.1.0 labels Apr 6, 2021
@pleku pleku enabled auto-merge (squash) April 6, 2021 09:47
* @return query parameters information
*/
public static QueryParameters fromString(String queryString) {
return new QueryParameters(parseQueryString(queryString));
Copy link
Collaborator

Choose a reason for hiding this comment

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

MINOR Immediately return this expression instead of assigning it to the temporary variable "parsedParams". rule

return Collections.singletonList(paramAndValue);
}
String param = paramAndValue.substring(0, index);
String value = paramAndValue.substring(index + 1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

MAJOR Define and throw a dedicated exception instead of using a generic one. rule

@vaadin-bot
Copy link
Collaborator

SonarQube analysis reported 2 issues

  • MAJOR 1 major
  • MINOR 1 minor

Watch the comments in this conversation to review them.

@pleku pleku merged commit a868f2f into master Apr 6, 2021
OLD Vaadin Flow ongoing work (Vaadin 10+) automation moved this from Iteration Reviews to Done - pending release Apr 6, 2021
@pleku pleku deleted the queryparams-parse branch April 6, 2021 11:07
pleku pushed a commit that referenced this pull request Aug 17, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
pleku pushed a commit that referenced this pull request Aug 17, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
pleku pushed a commit that referenced this pull request Aug 17, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
pleku pushed a commit that referenced this pull request Aug 17, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
pleku pushed a commit that referenced this pull request Aug 27, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
pleku pushed a commit that referenced this pull request Aug 30, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
caalador pushed a commit that referenced this pull request Aug 30, 2021
#10521)

A minor API behavior change: `Location:getQueryParameters` is unified with how `HttpServletRequest` works:
For a query string `?foo&bar` a list containing `""`  is returned for both `foo` and `bar` whereas the existing implementation returned empty lists.
@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with platform 14.7.0.rc1 and is also targeting the upcoming stable 14.7.0 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
OLD Vaadin Flow ongoing work (Vaadin ...
  
Done - pending release
Development

Successfully merging this pull request may close these issues.

None yet

3 participants