-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Handle java multipart form data on requests in test Helpers #11505
Conversation
c524a96
to
b6f1d44
Compare
b6f1d44
to
ba764a3
Compare
I hoped it could simply be possible to extend |
@martinariehm it seems like returning bytes from MultiPartFormData with |
First of all thanks for taking the time and providing this pull request! At first it seemed the changes you made were ok, I almost wanted to merge, however then I quickly set up a Play Java app with the "Reproducible Test Case" posted in #11496, running against a local Play build with this patch applied and ... it failed.
Since because we need to call Now with this scripted test I was able to reproduce the errors I just experienced
So the problem here was that you used Now, I was able to work around that by creating a writeable that handles Java's
So I got http 400 "bad request", but expected 200. After a bit debugging I found out that the payload of the 400 error displayed
So something had to be wrong with parsing the multipart/form-data request. And it was: The writables did not correctly escape the name field, fixed in the commit. And even worse: The boundary that is used for splitting the request body into multiple data/file parts was not consistent: The boundary supplied in the Content-Type header did not match any boundary in the request body. That's because the writable just generated its own boundary, not caring about the one of the content-type it got passed. So I fixed that as well (see commit) and now my tests did pass!
However I was not really satisfied with how this was implemented, because, like you already mentioned, this solution only works with
Yes, thanks great!
With my solution a framework user can use any "file" type. Like said, I implemented conversions for the most obvious ones.
The test was not monstrous. Scripted tests take much more resources and usually take much longer. Tests will never be too much, don't worry 😉 |
core/play-integration-test/src/it/java/play/routing/AbstractRoutingDslTest.java
Show resolved
Hide resolved
...sbt-test/play-sbt-plugin/java-test-helpers/src/test/java/controllers/HomeControllerTest.java
Show resolved
Hide resolved
...sbt-test/play-sbt-plugin/java-test-helpers/src/test/java/controllers/HomeControllerTest.java
Show resolved
Hide resolved
Just a note on this comment: If calling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martinariehm @adrianlyjak Let me know if you have any feedback or concerns regarding my solution. I think if you look at HomeControllerTest.java
you will see how my implemention works.
If you are good with this pr, I will merge it soon.
Maybe we can also backport parts of the pull request which do not break binary compatibility (basically my first solution until commit dd1f037
) to the 2.8.x branch (which would only support the TemporaryFile
classes though).
@mkurz this looks awesome! Thanks for the thorough review and for fixing it up, this all looks awesome to me! I put a few very minor comments on the multipart The scripted tests are really what I was looking for to verify this change, good to know about them. I saw them running in the github CI, but couldn't quite figure out what they were or how they worked. Still having some trouble. Looks like they depend on a
and then errors from
Is there some documentation or files you can point me to that might help me figure out how to run the scripted tests locally? |
Which comment? I can not see any. When I run into
I run To run scripted tests:
this makes sure the artifacts that get created in Anyway, to run the scripted tests, you should: $ sbt
sbt:Play-Framework> publishLocal
...
sbt:Play-Framework> project Sbt-Plugin
[info] set current project to Sbt-Plugin (in build file:...)
# Now set the versions to use
sbt:Sbt-Plugin> set scriptedSbt := "1.7.2"; set scriptedLaunchOpts += "-Dscala.version=2.13.10"; set scriptedLaunchOpts += "-Dscala.crossversions=2.13.10";
# You can now check if ithe versions got set correctly:
sbt:Sbt-Plugin> show scriptedSbt; show scriptedLaunchOpts;
# To now run a specific scripted test (e.g. the one in folder `java-test-helpers`):
sbt:Sbt-Plugin> scripted play-sbt-plugin/java-test-helpers
# To run all scripted tests just run:
sbt:Sbt-Plugin> scripted. There are docs, but I see they are not up-to-date: |
@adrianlyjak I opened #11549 to update the docs. |
|
@adrianlyjak Please check the last commit I pushed and my comments. If everything is good I think we can merge 👍 |
@mkurz LGTM, this all looks awesome! Thanks for your help and all the work you do for play framework. |
Fixes
Fixes #11496
Purpose
Handles the case of multipart form data in the java
Helpers
api so that java based routes and tests that accept multipart form data files can be properly tested.This is my first contribution here, so interested in feedback on implementation:
FilePart.asScala()
method to keep the codebase DRY. However this method is now in the public API. Is this acceptable? It seemed somewhat appropriate as there are a bunch of similar methods in the same file for similar classes to convert to scala.MultipartFormData[TemporaryFile]
is handled. The types are cooerced somewhat awkwardly, but seems like there's likely diminishing returns with how many cases should be handled here, and I'm somewhat unclear on whether other types of form data files are even supported? Currently if you send, e.g. aFilePart[String]
through, there will be another blow up in parsing internals from type casting. I could just ignore cases where theFilePart
is not matching, and perhaps throw a more descriptive exception at least?Pull Request Checklist