Add property to control 'path' field inclusion in error responses

By default it is included.

Closes gh-38619
This commit is contained in:
Moritz Halbritter
2023-12-05 08:37:13 +01:00
parent c4be302fdb
commit 2cce123bb5
12 changed files with 157 additions and 15 deletions

View File

@@ -55,6 +55,11 @@ public class ErrorProperties {
*/
private IncludeAttribute includeBindingErrors = IncludeAttribute.NEVER;
/**
* When to include "path" attribute.
*/
private IncludeAttribute includePath = IncludeAttribute.ALWAYS;
private final Whitelabel whitelabel = new Whitelabel();
public String getPath() {
@@ -97,6 +102,14 @@ public class ErrorProperties {
this.includeBindingErrors = includeBindingErrors;
}
public IncludeAttribute getIncludePath() {
return this.includePath;
}
public void setIncludePath(IncludeAttribute includePath) {
this.includePath = includePath;
}
public Whitelabel getWhitelabel() {
return this.whitelabel;
}

View File

@@ -54,6 +54,7 @@ import org.springframework.web.util.HtmlUtils;
*
* @author Brian Clozel
* @author Scott Frederick
* @author Moritz Halbritter
* @since 2.0.0
* @see ErrorAttributes
*/
@@ -168,6 +169,17 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
return getBooleanParameter(request, "errors");
}
/**
* Check whether the path attribute has been set on the given request.
* @param request the source request
* @return {@code true} if the path attribute has been requested, {@code false}
* otherwise
* @since 3.3.0
*/
protected boolean isPathEnabled(ServerRequest request) {
return getBooleanParameter(request, "path");
}
private boolean getBooleanParameter(ServerRequest request, String parameterName) {
String parameter = request.queryParam(parameterName).orElse("false");
return !"false".equalsIgnoreCase(parameter);

View File

@@ -75,6 +75,7 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
*
* @author Brian Clozel
* @author Scott Frederick
* @author Moritz Halbritter
* @since 2.0.0
*/
public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
@@ -164,6 +165,7 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
if (isIncludeBindingErrors(request, mediaType)) {
options = options.including(Include.BINDING_ERRORS);
}
options = isIncludePath(request, mediaType) ? options.including(Include.PATH) : options.excluding(Include.PATH);
return options;
}
@@ -177,7 +179,7 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
return switch (this.errorProperties.getIncludeStacktrace()) {
case ALWAYS -> true;
case ON_PARAM -> isTraceEnabled(request);
default -> false;
case NEVER -> false;
};
}
@@ -191,7 +193,7 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
return switch (this.errorProperties.getIncludeMessage()) {
case ALWAYS -> true;
case ON_PARAM -> isMessageEnabled(request);
default -> false;
case NEVER -> false;
};
}
@@ -205,7 +207,22 @@ public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHa
return switch (this.errorProperties.getIncludeBindingErrors()) {
case ALWAYS -> true;
case ON_PARAM -> isBindingErrorsEnabled(request);
default -> false;
case NEVER -> false;
};
}
/**
* Determine if the path attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the path attribute should be included
* @since 3.3.0
*/
protected boolean isIncludePath(ServerRequest request, MediaType produces) {
return switch (this.errorProperties.getIncludePath()) {
case ALWAYS -> true;
case ON_PARAM -> isPathEnabled(request);
case NEVER -> false;
};
}

View File

@@ -41,6 +41,7 @@ import org.springframework.web.servlet.ModelAndView;
* @author Dave Syer
* @author Phillip Webb
* @author Scott Frederick
* @author Moritz Halbritter
* @since 1.3.0
* @see ErrorAttributes
*/
@@ -74,18 +75,43 @@ public abstract class AbstractErrorController implements ErrorController {
return this.errorAttributes.getErrorAttributes(webRequest, options);
}
/**
* Returns whether the trace parameter is set.
* @param request the request
* @return whether the trace parameter is set
*/
protected boolean getTraceParameter(HttpServletRequest request) {
return getBooleanParameter(request, "trace");
}
/**
* Returns whether the message parameter is set.
* @param request the request
* @return whether the message parameter is set
*/
protected boolean getMessageParameter(HttpServletRequest request) {
return getBooleanParameter(request, "message");
}
/**
* Returns whether the errors parameter is set.
* @param request the request
* @return whether the errors parameter is set
*/
protected boolean getErrorsParameter(HttpServletRequest request) {
return getBooleanParameter(request, "errors");
}
/**
* Returns whether the path parameter is set.
* @param request the request
* @return whether the path parameter is set
* @since 3.3.0
*/
protected boolean getPathParameter(HttpServletRequest request) {
return getBooleanParameter(request, "path");
}
protected boolean getBooleanParameter(HttpServletRequest request, String parameterName) {
String parameter = request.getParameter(parameterName);
if (parameter == null) {

View File

@@ -49,6 +49,7 @@ import org.springframework.web.servlet.ModelAndView;
* @author Michael Stummvoll
* @author Stephane Nicoll
* @author Scott Frederick
* @author Moritz Halbritter
* @since 1.0.0
* @see ErrorAttributes
* @see ErrorProperties
@@ -121,6 +122,7 @@ public class BasicErrorController extends AbstractErrorController {
if (isIncludeBindingErrors(request, mediaType)) {
options = options.including(Include.BINDING_ERRORS);
}
options = isIncludePath(request, mediaType) ? options.including(Include.PATH) : options.excluding(Include.PATH);
return options;
}
@@ -134,7 +136,7 @@ public class BasicErrorController extends AbstractErrorController {
return switch (getErrorProperties().getIncludeStacktrace()) {
case ALWAYS -> true;
case ON_PARAM -> getTraceParameter(request);
default -> false;
case NEVER -> false;
};
}
@@ -148,7 +150,7 @@ public class BasicErrorController extends AbstractErrorController {
return switch (getErrorProperties().getIncludeMessage()) {
case ALWAYS -> true;
case ON_PARAM -> getMessageParameter(request);
default -> false;
case NEVER -> false;
};
}
@@ -162,7 +164,22 @@ public class BasicErrorController extends AbstractErrorController {
return switch (getErrorProperties().getIncludeBindingErrors()) {
case ALWAYS -> true;
case ON_PARAM -> getErrorsParameter(request);
default -> false;
case NEVER -> false;
};
}
/**
* Determine if the path attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the path attribute should be included
* @since 3.3.0
*/
protected boolean isIncludePath(HttpServletRequest request, MediaType produces) {
return switch (getErrorProperties().getIncludePath()) {
case ALWAYS -> true;
case ON_PARAM -> getPathParameter(request);
case NEVER -> false;
};
}

View File

@@ -112,8 +112,7 @@ class ErrorMvcAutoConfigurationTests {
}
private ErrorAttributeOptions withAllOptions() {
return ErrorAttributeOptions.of(Include.EXCEPTION, Include.STACK_TRACE, Include.MESSAGE,
Include.BINDING_ERRORS);
return ErrorAttributeOptions.of(Include.values());
}
}