I have a spring boot application with embedded tomcat , whenever there is a server error occurs, I want to hide the apache tomcat version on error page.
As far as I know; the most known solutions are adding server.properties to web.xml or zipping the catalina jar.
Since the application does not have web.xml, I can't figure it out to hide tomcat version.
Tomcat server properties were changed as below but none of them worked.
server.error.include-stacktrace=never
server.error.whitelabel.enabled=false
Spring boot version : 2.5.4
Please refer the picture.
Thanks!
CodePudding user response:
It may be same issue as following:
import java.io.IOException;
import java.io.Writer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ErrorReportValve;
import org.apache.coyote.ActionCode;
import org.apache.tomcat.util.ExceptionUtils;
public class CustomErrorReportValve extends ErrorReportValve {
// Create a simple logger
Logger log = Logger.getLogger(CustomErrorReportValve.class.getName());
@Override
protected void report(final Request request, final Response response, final Throwable throwable) {
// ref: ErrorReportValve implementation
final int statusCode = response.getStatus();
// Do nothing on a 1xx, 2xx and 3xx status
// Do nothing if anything has been written already
// Do nothing if the response hasn't been explicitly marked as in error
// and that error has not been reported.
if (statusCode < 400 || response.getContentWritten() > 0 || !response.setErrorReported()) {
return;
}
// If an error has occurred that prevents further I/O, don't waste time
// producing an error report that will never be read
final AtomicBoolean result = new AtomicBoolean(false);
response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
if (!result.get()) {
return;
}
try {
try {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
} catch (final Throwable t) {
ExceptionUtils.handleThrowable(t);
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("status.setContentType", t);
}
}
final Writer writer = response.getReporter();
if (writer != null) {
// If writer is null, it's an indication that the response has
// been hard committed already, which should never happen
writer.write("<!doctype html><html lang=\"en\"><title>error</title><body>Error occured.</body></html>");
response.finishResponse();
}
} catch (IOException | IllegalStateException e) {
// Ignore
}
}
}
import org.apache.catalina.Container;
import org.apache.catalina.core.StandardHost;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyConfig {
// https://docs.spring.io/spring-boot/docs/2.5.4/reference/htmlsingle/#howto-use-tomcat-legacycookieprocessor
// https://github.com/spring-projects/spring-boot/issues/21257#issuecomment-745565376
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> errorReportValveCustomizer() {
return (factory) -> {
factory.addContextCustomizers(context -> {
final Container parent = context.getParent();
if (parent instanceof StandardHost) {
// above class FQCN
((StandardHost) parent).setErrorReportValveClass(
"com.example.foo.bar.CustomErrorReportValve");
}
});
};
}
}
CodePudding user response:
For embedded tomcat, I found configuration to override error report valve
Now the response does not have tomcat version.
var host = (StandardHost) tomcat.getHost();
var errorReportValve = new org.apache.catalina.valves.ErrorReportValve();
errorReportValve.setShowReport(false);
errorReportValve.setShowServerInfo(false);
host.addValve(errorReportValve);