-
Bug
-
Resolution: Unresolved
-
Major
-
2.3.14.Final
HTTP specifies client error 413 (The request entity is larger than the server will accept) for when request content exceeds the configured maximum length. However, when this happens Undertow responds with HTTP 500 (Server Error). This results in the client being unable to provide the user with a useful indication of what went wrong.
More generally, there appears to be no uniform way to handle specific exceptions thrown by HTTP request handlers in the overall Undertow codebase.
In this specific case, the problem appears to be rooted in MultiPartParserDefinition.data() at/around line 326, specifically the following check:
if (this.maxIndividualFileSize > 0 && this.currentFileSize > this.maxIndividualFileSize)
throw UndertowMessages.MESSAGES.maxFileSizeExceeded(this.maxIndividualFileSize);
}
Throwing the `FileTooLargeException` is fine, except that the code subsequently catches the all exceptions and simply logs and sends the 500 response, like so (at/about line 483, if I have followed the code correctly):
} catch (Throwable e) {
UndertowLogger.REQUEST_IO_LOGGER.debug("Exception parsing data", e);
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
exchange.endExchange();
}
It seems like in Undertow the intention is to be able to handle exceptions as is illustrated by the ExceptionHandler handler, but the way this handler is coded prevents that. The alternative is to use a DefaultResponseListener but by the time that is invoked there is nothing for it to use to identify they cause of the 500 error (i.e. it does not know that the error was an attempt to upload a file that exceeds the limit).
Is there anything I am overlooking, or is this a bug? If the latter, then it seems to be a problem in numerous handlers as a quick search for "catch" in server/handlers has 175 results in 80 files.
At the very least, all such occurrences could attach the specific exception to the exchange object (using the existing ExceptionHandler.THROWABLE key), allowing request post processing to query it and change the 500 to something more specific (in this case the exception is specific enough to concretely return 413). I would recommend that they also attach the string handler name or the handler class so that a global default handler can factor in the handler which failed when transforming the error to something more useful to the client (for example, by adding ExceptionHandler.FAILING_HANDLER).
Our current crude work-around is to assume that any failure while handling form data is due to an overly large file, which is obviously too coarse, but should get us by for a little while until a fix is available. Like this:
if(exc.getStatusCode()==RSP_SRVERR) {
//FIXME:LD:2024-10-14: This could actually be any failure, but an enhancement is needed in Undertow to save the
// underlying exception in the exchange object so it can be queried here. For now we are assuming that the only
// failure will be uploading too much data.
setResponse(exc,RSP_BIGENT,"Request data rejected (uploaded file exceeds configured maximum of " + uploadMaximumKb + "KB)");
{
{ }}}