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

WSRequest: Normalize URL #288

Closed
wants to merge 1 commit into from
Closed

Conversation

htmldoug
Copy link
Contributor

@htmldoug htmldoug commented Oct 29, 2018

Pull Request Checklist

  • Have you read through the contributor guidelines?
  • Have you signed the Typesafe CLA?
  • Have you squashed your commits?
  • Have you added copyright headers to new files?
  • Have you checked that both Scala and Java APIs are updated?
  • Have you updated the documentation for both Scala and Java sections?
  • Have you added tests for any changed functionality?

Fixes

Fixes #267

Purpose

Ensure that StandaloneWSRequest.uri does not return invalid values or throw, by normalizing the url: String when a StandaloneWSRequest is constructed. Same approach is used by the java implementation.

Background Context

This approach follows the "tolerant" recommendation, #267 (comment).

Ensures:

  1. StandaloneWSRequest.url path is encoded.
  2. Any query params present in the URL are moved to StandaloneWSRequest.queryString.

Implementation is based upon a WSRequestFilter-like decorator I've been using in production since June 2018. An advantage to fixing the request right away is that request.uri can be invoked safely sooner in the process.

Caveats

Normalization can still be bypassed by:

  • StandaloneAhcWSClient.copy(url = ">^..^<", ...)
  • new StandaloneAhcWSRequest(client, ">^..^<", ...)

@htmldoug htmldoug changed the title WIP: WSRequest: Normalize URL WSRequest: Normalize URL Nov 18, 2018
@htmldoug
Copy link
Contributor Author

@marcospereira I've removed "WIP", and I'm ready for a review now, please.

@htmldoug
Copy link
Contributor Author

@gmethvin @wsargent ready for review. I see your fingerprints here from #80 and #189.

@htmldoug
Copy link
Contributor Author

htmldoug commented Dec 9, 2018

@marcospereira @gmethvin @wsargent can I get a review please?

@wsargent
Copy link
Member

I'm free this weekend, I can take a look at it

@wsargent wsargent self-requested a review December 13, 2018 21:10
Copy link
Member

@wsargent wsargent left a comment

Choose a reason for hiding this comment

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

So I can see from the PR that there's some use of UriEncoder.FIXING and the path and the query parameters are touched, but it's not clear in the code what the overall effect is.

Copy link
Member

@wsargent wsargent left a comment

Choose a reason for hiding this comment

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

I think this is useful but it leaves some ambiguities into what encoding means and what the end result is.

Tying things down to a particular RFC and providing examples would help, as would "boundary conditions" showing the normalize method will cover and what it won't. More unit tests showing failed URLs and URLs which can't be recovered would be good too.

}

/**
* Builds an AHC [[Uri]] with all parts URL encoded.
Copy link
Member

Choose a reason for hiding this comment

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

Can we specify the RFC here used for the encoding?

Copy link
Contributor Author

@htmldoug htmldoug Jan 22, 2019

Choose a reason for hiding this comment

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

I'm not sure we can.

I assume UriEncoder.FIXING returns an org.asynchttpclient.uri.Uri capable of producing an RFC 3986 compliant String. It makes no guarantees in the javadoc, but the private static constant names in Utf8UrlEncoder mention RFC3986. I'm not sure we can go so far as to claim that the Uri result conforms to the RFC though. The result seems closer to it at least.

The goal is just to get it closer to returning a valid java.net.URI, which claims to represent RFC 2396, "aside from minor deviations".

I've updated the scaladoc of this method to say that it runs it through UriEncoder.FIXING, which is at least 100% accurate.

@htmldoug
Copy link
Contributor Author

@wsargent thanks for the review. I'll update with RFC links, examples, and more tests.

@htmldoug htmldoug force-pushed the uri-fixing branch 7 times, most recently from 7ae88ee to 8a8eb17 Compare January 22, 2019 02:26
} yield key -> value

req
.withUrl(urlNoQueryParams)
Copy link
Contributor Author

@htmldoug htmldoug Jan 22, 2019

Choose a reason for hiding this comment

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

One concern: withUrl() calls normalize() here which could lead to infinite mutual recursion if I missed a case. I'd prefer to call the StandaloneAhcWSRequest.copy() escape hatch here, but it requires access to the implicit Materializer which is not accessible.

Some ideas in order of preference (least -> most):

  • Leave it as is and let users report cases we missed. Should happen pretty quickly, but ugh.
  • Remove the check from withUrl(). That'd weaken the integrity of StandaloneAhcWSRequest, although it's already compromisable with copy() if you provide your own Materializer.
  • Change visibility to StandaloneAhcWSRequest(...)(implicit private[ahc] val materializer: Materializer) and do the copy().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm going to go ahead and push up a second commit with the last approach. If you like it, I'll squash. Otherwise, I'll drop it.

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. Thoughts?

@htmldoug
Copy link
Contributor Author

Thanks again for the review and sorry for the long delay. Holidays derailed me, but https://blog.playframework.com/play-2-7-0-rc9-released/ was a nice kick in the pants.

I've addressed all comments, and added benchmarks and more tests. Ready for another review.

@htmldoug
Copy link
Contributor Author

@marcospereira @wsargent do you guys need anything else from me for this to be mergeable?

@htmldoug
Copy link
Contributor Author

htmldoug commented Apr 7, 2019

We're starting on the play 2.7 upgrade now. Any chance of getting this merged, or should we just port this to a wrapper and wrap all of our WSClients to keep WSRequest.uri from throwing runtime exceptions? It sure would be nice to avoid that.

@jeffmay
Copy link

jeffmay commented Jun 3, 2019

Any update on this? I would like to upgrade to Play 2.7 with this as well, and I have the same issue that Doug is trying to solve here.

@htmldoug
Copy link
Contributor Author

htmldoug commented Jun 3, 2019

It's been ready to go since #288 (comment). I've rebased onto latest master, although after master bumped to play 2.8.0-M1, I'm not sure if this will be available for play 2.7.

@wsargent do you plan to re-review or should I close the PR?

@htmldoug htmldoug mentioned this pull request Jun 10, 2019
7 tasks
@htmldoug
Copy link
Contributor Author

Closing due to lack of review. I'll leave #267 open. I've put up a much smaller #353 to document current behavior.

@htmldoug htmldoug closed this Jun 10, 2019
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.

StandaloneWSClient.url(String) permits inconsistent states with query params
4 participants