Skip to content
Merged
35 changes: 30 additions & 5 deletions api/src/org/labkey/api/action/SpringActionController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -73,6 +74,8 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.ModelAndView;
Expand Down Expand Up @@ -367,6 +370,11 @@ private ModelAndView handleBadRequestException(HttpServletRequest request, HttpS
}

private ModelAndView handleBadRequestException(HttpServletRequest request, HttpServletResponse response, Controller controller, BadRequestException x) throws Exception
{
return handleBadRequestException(request, response, controller, x, HttpServletResponse.SC_BAD_REQUEST);
}

private ModelAndView handleBadRequestException(HttpServletRequest request, HttpServletResponse response, Controller controller, BadRequestException x, int status) throws Exception
{
// TODO: we are assuming that all ApiActions respond with JSON and all !ApiAction respond HTML. Would be better to be explicit.
boolean jsonResponse = controller instanceof BaseApiAction;
Expand All @@ -379,13 +387,13 @@ private ModelAndView handleBadRequestException(HttpServletRequest request, HttpS
{
// Issue 53120: Set content-type, status when responding with JSON content
response.setContentType(ApiJsonWriter.CONTENT_TYPE_JSON);
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setStatus(status);
}

Writer w = response.getWriter();
JSONObject json = new JSONObject();
json.put("success", false);
json.put("status", HttpServletResponse.SC_BAD_REQUEST);
json.put("status", status);
json.put("exception", x.getMessage());
if (htmlWrappedJson)
w.write("<html><body><textarea>");
Expand All @@ -397,7 +405,7 @@ private ModelAndView handleBadRequestException(HttpServletRequest request, HttpS

if (textResponse)
{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setStatus(status);
response.setContentType("text/plain");
Writer w = response.getWriter();
w.write(x.getMessage());
Expand All @@ -407,7 +415,7 @@ private ModelAndView handleBadRequestException(HttpServletRequest request, HttpS
// TODO design/text for custom view
if (x instanceof AntiVirusException)
{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setStatus(status);
HttpView<?> view = SimpleErrorView.fromMessage(x.getMessage());

PageConfig page = new PageConfig(request);
Expand All @@ -416,7 +424,7 @@ private ModelAndView handleBadRequestException(HttpServletRequest request, HttpS
return null;
}

response.sendError(HttpServletResponse.SC_BAD_REQUEST, x.getMessage());
response.sendError(status, x.getMessage());
return null;
}

Expand Down Expand Up @@ -538,6 +546,23 @@ public ModelAndView handleRequest(HttpServletRequest request, @NotNull HttpServl
// TODO Better/custom error report page/response
if (x.getCause() instanceof BadRequestException)
return handleBadRequestException(request, response, controller, (BadRequestException)x.getCause());
if (x instanceof MultipartException && ExceptionUtil.isClientRequestFailure(x))
{
_log.debug("Unable to parse multipart request", x);
int status;
String message;
if (x instanceof MaxUploadSizeExceededException)
{
status = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE;
message = StringUtils.defaultIfBlank(ExceptionUtils.getRootCause(x).getMessage(), x.getMessage());
}
else
{
status = HttpServletResponse.SC_BAD_REQUEST;
message = "Unable to parse multipart request";
}
return handleBadRequestException(request, response, controller, new BadRequestException(message, x), status);
}
throw x;
}
}
Expand Down
12 changes: 11 additions & 1 deletion api/src/org/labkey/api/module/DefaultModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,17 @@ public void dispatch(HttpServletRequest request, HttpServletResponse response, A
return;
}

ViewContext rootContext = new ViewContext(request, response, url);
ViewContext rootContext;
try
{
rootContext = new ViewContext(request, response, url);
}
// First parameter read; unparseable parameters would otherwise escape to Tomcat's own error handling
catch (IllegalStateException x)
{
ExceptionUtil.handleException(request, response, x, null, false);
return;
}

Container container = rootContext.getContainer();
if (container != null && !isAvailable(container))
Expand Down
Loading
Loading