Canceled file uploads raise ClosedChannelExceptions caught in RequestBodyHandler
See original GitHub issueThanks to the wonderful Play! Framework v2.2.0 my application enables users to upload large files to a server. On the client side I utilize Javascript and a XMLHttpRequest() object to monitor the progress of the uploads. The corresponding controller on the server side looks like this
def upload = isAuthenticated(parse.multipartFormData) { user => implicit request =>
request.body.file("file").map { file =>
import java.io.File
val filepath = "/tmp/" + file.filename
file.ref.moveTo(new File(filepath), true)
Ok("Success")
}.getOrElse {
Logger.warn("A file upload has been canceled by the user or it failed.")
Redirect(routes.Application.userPanel)
}
}
The upload works as expected if the user does not interrupt the upload process (e.g. by navigating to another website or by aborting the transfer through request.abort()), but if the upload is purposely canceled by the user (or somehow interrupted) my console gets cluttered with ClosedChannelExceptions caught in RequestBodyHandler:
[warn] application - A file upload has been canceled by the user or it failed.
[error] play - Exception caught in RequestBodyHandler
java.nio.channels.ClosedChannelException: null
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:434) ~[netty.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:129) ~[netty.jar:na]
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:99) ~[netty.jar:na]
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:36) ~[netty.jar:na]
at org.jboss.netty.channel.Channels.write(Channels.java:725) ~[netty.jar:na]
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.doEncode(OneToOneEncoder.java:71) ~[netty.jar:na]
I had a look at the sources of the RequestBodyHandler and it seams like you suppress NPEs in v2.1.x like this:
override def exceptionCaught(ctx: ChannelHandlerContext, e: ExceptionEvent) = {
e.getCause match {
case e: NullPointerException => Play.logger.debug("NPE thrown in RequestBodyHandler, parsing probably ended early", e)
case other => Play.logger.error("Error in request body handler", e.getCause)
}
e.getChannel.close() /*really? */
}
But I could not find such a measure in v.2.2.x. Wouldn’t it be good to suppress the netty exceptions in the new version too? Since a canceled file upload is a very common thing and happens frequently, there should be a way to get rid of such logs.
Thank you very much for your effort.
Issue Analytics
- State:
- Created 10 years ago
- Comments:11 (7 by maintainers)
As @cchantep explained, his custom body parser is a workaround and does not support chunked responses. Now that we’ve moved to Akka streams, we can pass the error through as a failed
Accumulator
.If you are still seeing an issue like this in Play 2.5 or 2.6, it may be best to open a new issue to discuss, since much has changed in Play since this bug was created.
To whom may be interested, the following can be used as workaround with Play 2.4 (should be usable with 2.3), as long as chunked request is not used.