diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/RestApiException.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/RestApiException.java index a6d27cd2bc..3fae128300 100644 --- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/RestApiException.java +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/RestApiException.java @@ -17,6 +17,7 @@ package com.google.gerrit.extensions.restapi; /** Root exception type for JSON API failures. */ public abstract class RestApiException extends Exception { private static final long serialVersionUID = 1L; + private CacheControl caching = CacheControl.NONE; public RestApiException() { } @@ -28,4 +29,14 @@ public abstract class RestApiException extends Exception { public RestApiException(String msg, Throwable cause) { super(msg, cause); } + + public CacheControl caching() { + return caching; + } + + @SuppressWarnings("unchecked") + public T caching(CacheControl c) { + caching = c; + return (T) this; + } } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java index ff65674511..e0bef35087 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RunAsFilter.java @@ -77,7 +77,7 @@ class RunAsFilter implements Filter { String runas = req.getHeader(RUN_AS); if (runas != null) { if (!enabled) { - RestApiServlet.replyError(res, + RestApiServlet.replyError(req, res, SC_FORBIDDEN, RUN_AS + " disabled by auth.enableRunAs = false"); return; @@ -85,7 +85,7 @@ class RunAsFilter implements Filter { CurrentUser self = session.get().getCurrentUser(); if (!self.getCapabilities().canRunAs()) { - RestApiServlet.replyError(res, + RestApiServlet.replyError(req, res, SC_FORBIDDEN, "not permitted to use " + RUN_AS); return; @@ -96,13 +96,13 @@ class RunAsFilter implements Filter { target = accountResolver.find(runas); } catch (OrmException e) { log.warn("cannot resolve account for " + RUN_AS, e); - RestApiServlet.replyError(res, + RestApiServlet.replyError(req, res, SC_INTERNAL_SERVER_ERROR, "cannot resolve " + RUN_AS); return; } if (target == null) { - RestApiServlet.replyError(res, + RestApiServlet.replyError(req, res, SC_FORBIDDEN, "no account matches " + RUN_AS); return; diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/ParameterParser.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/ParameterParser.java index 371e9ea47d..9183d5c3c2 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/ParameterParser.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/ParameterParser.java @@ -68,7 +68,7 @@ class ParameterParser { clp.parseOptionMap(in); } catch (CmdLineException e) { if (!clp.wasHelpRequestedByOption()) { - replyError(res, SC_BAD_REQUEST, e.getMessage()); + replyError(req, res, SC_BAD_REQUEST, e.getMessage()); return false; } } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java index ba6c5bc732..62bc81690c 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java @@ -321,27 +321,27 @@ public class RestApiServlet extends HttpServlet { } } } catch (AuthException e) { - replyError(res, status = SC_FORBIDDEN, e.getMessage()); + replyError(req, res, status = SC_FORBIDDEN, e.getMessage(), e.caching()); } catch (BadRequestException e) { - replyError(res, status = SC_BAD_REQUEST, e.getMessage()); + replyError(req, res, status = SC_BAD_REQUEST, e.getMessage(), e.caching()); } catch (MethodNotAllowedException e) { - replyError(res, status = SC_METHOD_NOT_ALLOWED, "Method not allowed"); + replyError(req, res, status = SC_METHOD_NOT_ALLOWED, "Method not allowed", e.caching()); } catch (ResourceConflictException e) { - replyError(res, status = SC_CONFLICT, e.getMessage()); + replyError(req, res, status = SC_CONFLICT, e.getMessage(), e.caching()); } catch (PreconditionFailedException e) { - replyError(res, status = SC_PRECONDITION_FAILED, - Objects.firstNonNull(e.getMessage(), "Precondition failed")); + replyError(req, res, status = SC_PRECONDITION_FAILED, + Objects.firstNonNull(e.getMessage(), "Precondition failed"), e.caching()); } catch (ResourceNotFoundException e) { - replyError(res, status = SC_NOT_FOUND, "Not found"); + replyError(req, res, status = SC_NOT_FOUND, "Not found", e.caching()); } catch (UnprocessableEntityException e) { - replyError(res, status = 422, - Objects.firstNonNull(e.getMessage(), "Unprocessable Entity")); + replyError(req, res, status = 422, + Objects.firstNonNull(e.getMessage(), "Unprocessable Entity"), e.caching()); } catch (AmbiguousViewException e) { - replyError(res, status = SC_NOT_FOUND, e.getMessage()); + replyError(req, res, status = SC_NOT_FOUND, e.getMessage()); } catch (MalformedJsonException e) { - replyError(res, status = SC_BAD_REQUEST, "Invalid " + JSON_TYPE + " in request"); + replyError(req, res, status = SC_BAD_REQUEST, "Invalid " + JSON_TYPE + " in request"); } catch (JsonParseException e) { - replyError(res, status = SC_BAD_REQUEST, "Invalid " + JSON_TYPE + " in request"); + replyError(req, res, status = SC_BAD_REQUEST, "Invalid " + JSON_TYPE + " in request"); } catch (Exception e) { status = SC_INTERNAL_SERVER_ERROR; handleException(e, req, res); @@ -837,14 +837,20 @@ public class RestApiServlet extends HttpServlet { if (!res.isCommitted()) { res.reset(); - replyError(res, SC_INTERNAL_SERVER_ERROR, "Internal server error"); + replyError(req, res, SC_INTERNAL_SERVER_ERROR, "Internal server error"); } } - public static void replyError(HttpServletResponse res, int statusCode, - String msg) throws IOException { + public static void replyError(HttpServletRequest req, + HttpServletResponse res, int statusCode, String msg) throws IOException { + replyError(req, res, statusCode, msg, CacheControl.NONE); + } + + public static void replyError(HttpServletRequest req, + HttpServletResponse res, int statusCode, String msg, + CacheControl c) throws IOException { res.setStatus(statusCode); - CacheHeaders.setNotCacheable(res); + configureCaching(req, res, c); replyText(null, res, msg); }