-
-
Notifications
You must be signed in to change notification settings - Fork 67
Description
Minimal repro:
case class FormRoute()(implicit
cc: castor.Context,
log: cask.Logger
) extends cask.MainRoutes:
@cask.get("/")
def index() =
Response("""
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<form action="/post" method="post" enctype="multipart/form-data">
<input type="file" id="image" name="image" accept="image/*">
<button type="submit">Submit</button>
</form>
</body>
</html>
""", 200, Seq(("Content-Type", "text/html")))
@cask.postForm("/post")
def post(image: cask.FormFile) = s"Image filename: ${image.fileName}"
initialize()
object Application extends cask.Main:
val allRoutes = Seq(FormRoute())
Stacktrace:
Unable to parse form data: java.lang.IllegalStateException: UT000017: Form value is a file, use getFileItem() instead
java.lang.IllegalStateException: UT000017: Form value is a file, use getFileItem() instead
at io.undertow.server.handlers.form.FormData$FormValueImpl.getValue(FormData.java:351)
at cask.model.FormEntry$.fromUndertow(Params.scala:102)
The method cask.model.FormEntry#fromUndertow is naively implemented and does not take into account optional field values. Browsers AFAIK will always send fields even if they are empty, it's up to the server/app to decide what emptiness means.
At the very least I would expect fromUndertow to return Option[FormEntry] and let the postForm decorator deal with it.
Below is an example request from Firefox, but I would expect all browsers to behave the same.
-----------------------------265322345236697440593672026017
Content-Disposition: form-data; name="image"; filename=""
Content-Type: application/octet-stream
-----------------------------265322345236697440593672026017--
I tried to take a stab at fixing this but the project doesn't compile (tried all tags as low as 0.9.0) and the error messages are too cryptic for me (scala.reflect.internal.FatalError: bad constant pool index: 0 at pos: 48454 wtf?!). Let me know if you want me to open a ticket for that also.